📄 cfsocket.cpp
字号:
addr = (struct sockaddr_un *)address->m_addr; strncpy(path, addr->sun_path, sbuf); return GSOCK_NOERROR;}/* Address handling *//* GSocket_SetLocal: * GSocket_GetLocal: * GSocket_SetPeer: * GSocket_GetPeer: * Set or get the local or peer address for this socket. The 'set' * functions return GSOCK_NOERROR on success, an error code otherwise. * The 'get' functions return a pointer to a GAddress object on success, * or NULL otherwise, in which case they set the error code of the * corresponding GSocket. * * Error codes: * GSOCK_INVSOCK - the socket is not valid. * GSOCK_INVADDR - the address is not valid. */GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address){ assert( socket != NULL ); // the socket must be initialized, or it must be a server if ((socket->m_fd != INVALID_SOCKET && !socket->m_server)) { socket->m_error = GSOCK_INVSOCK; return GSOCK_INVSOCK; } // check address if (address == NULL || address->m_family == GSOCK_NOFAMILY) { socket->m_error = GSOCK_INVADDR; return GSOCK_INVADDR; } if (socket->m_local) GAddress_destroy(socket->m_local); socket->m_local = GAddress_copy(address); return GSOCK_NOERROR;}GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address){ assert(socket != NULL); // check address if (address == NULL || address->m_family == GSOCK_NOFAMILY) { socket->m_error = GSOCK_INVADDR; return GSOCK_INVADDR; } if (socket->m_peer) GAddress_destroy(socket->m_peer); socket->m_peer = GAddress_copy(address); return GSOCK_NOERROR;}GAddress *GSocket_GetLocal(GSocket *socket){ GAddress *address; struct sockaddr addr; socklen_t size = sizeof(addr); GSocketError err; assert( socket != NULL ); // try to get it from the m_local var first if (socket->m_local) return GAddress_copy(socket->m_local); // else, if the socket is initialized, try getsockname if (socket->m_fd == INVALID_SOCKET) { socket->m_error = GSOCK_INVSOCK; return NULL; } if (getsockname(socket->m_fd, &addr, (socklen_t *) &size) < 0) { socket->m_error = GSOCK_IOERR; return NULL; } // got a valid address from getsockname, create a GAddress object address = GAddress_new(); if (address == NULL) { socket->m_error = GSOCK_MEMERR; return NULL; } err = _GAddress_translate_from(address, &addr, size); if (err != GSOCK_NOERROR) { GAddress_destroy(address); socket->m_error = err; return NULL; } return address;}GAddress *GSocket_GetPeer(GSocket *socket){ assert(socket != NULL); // try to get it from the m_peer var if (socket->m_peer) return GAddress_copy(socket->m_peer); return NULL;}GSocket *GSocket_new(void){ GSocket *socket; socket = (GSocket *)malloc(sizeof(GSocket)); if (socket == NULL) return NULL; socket->m_fd = INVALID_SOCKET; for (int i=0;i<GSOCK_MAX_EVENT;i++) { socket->m_cbacks[i] = NULL; } socket->m_detected = 0; socket->m_local = NULL; socket->m_peer = NULL; socket->m_error = GSOCK_NOERROR; socket->m_non_blocking = false ; socket->m_stream = true;// socket->m_oriented = true; socket->m_server = false; socket->m_establishing = false; socket->m_timeout = 10 * 60 * 1000; // 10 minutes * 60 sec * 1000 millisec socket->m_cfSocket = NULL ; socket->m_runLoopSource = NULL ; socket->m_readStream = NULL; socket->m_writeStream = NULL; return socket ;}void GSocket_close(GSocket *socket){ if ( socket->m_cfSocket != NULL ) { if ( socket->m_readStream ) { CFReadStreamClose(socket->m_readStream); CFRelease( socket->m_readStream ) ; socket->m_readStream = NULL ; } if ( socket->m_writeStream ) { CFWriteStreamClose(socket->m_writeStream); CFRelease( socket->m_writeStream ) ; socket->m_writeStream = NULL ; } CFSocketInvalidate( socket->m_cfSocket ) ; CFRelease( socket->m_cfSocket ) ; socket->m_cfSocket = NULL ; socket->m_fd = INVALID_SOCKET ; }}void GSocket_Shutdown(GSocket *socket){ GSocket_close( socket ); // Disable GUI callbacks for (int evt = 0; evt < GSOCK_MAX_EVENT; evt++) socket->m_cbacks[evt] = NULL; socket->m_detected = GSOCK_LOST_FLAG;}void GSocket_destroy(GSocket *socket){ assert( socket != NULL ); // Check that the socket is really shut down if (socket->m_fd != INVALID_SOCKET) GSocket_Shutdown(socket); // Destroy private addresses if (socket->m_local) GAddress_destroy(socket->m_local); if (socket->m_peer) GAddress_destroy(socket->m_peer); // Destroy the socket itself free(socket);}GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream){ assert( socket != NULL ); if (socket->m_fd != INVALID_SOCKET) { socket->m_error = GSOCK_INVSOCK; return GSOCK_INVSOCK; } if (!socket->m_peer) { socket->m_error = GSOCK_INVADDR; return GSOCK_INVADDR; } // Streamed or dgram socket? socket->m_stream = (stream == GSOCK_STREAMED); socket->m_oriented = true; socket->m_server = false; socket->m_establishing = false; GSocketError returnErr = GSOCK_NOERROR ; CFSocketError err ; CFAllocatorRef alloc = kCFAllocatorDefault ; CFSocketContext ctx ; memset( &ctx , 0 , sizeof( ctx ) ) ; ctx.info = socket ; socket->m_cfSocket = CFSocketCreate( alloc , socket->m_peer->m_realfamily , stream == GSOCK_STREAMED ? SOCK_STREAM : SOCK_DGRAM , 0 , kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack , wxMacCFSocketCallback , &ctx ) ; _GSocket_Enable(socket, GSOCK_CONNECTION); socket->m_fd = CFSocketGetNative( socket->m_cfSocket ) ; CFStreamCreatePairWithSocket ( alloc , socket->m_fd , &socket->m_readStream , &socket->m_writeStream ); if ((socket->m_readStream == NULL) || (socket->m_writeStream == NULL)) { GSocket_close(socket); socket->m_error = GSOCK_IOERR; return GSOCK_IOERR; } if ( !CFReadStreamOpen( socket->m_readStream ) || !CFWriteStreamOpen( socket->m_writeStream ) ) { GSocket_close(socket); socket->m_error = GSOCK_IOERR; return GSOCK_IOERR; } CFRunLoopSourceRef rls = CFSocketCreateRunLoopSource(alloc , socket->m_cfSocket , 0); CFRunLoopAddSource(CFRunLoopGetCurrent() , rls, kCFRunLoopCommonModes); CFRelease(rls); CFDataRef address = CFDataCreateWithBytesNoCopy(alloc, (const UInt8*) socket->m_peer->m_addr, socket->m_peer->m_len , kCFAllocatorNull); if ( !address ) return GSOCK_MEMERR ; err = CFSocketConnectToAddress( socket->m_cfSocket , address, socket->m_non_blocking ? -1 : socket->m_timeout / 1000 ) ; CFRelease(address); if (err != kCFSocketSuccess) { if ( err == kCFSocketTimeout ) { GSocket_close(socket); socket->m_error = GSOCK_TIMEDOUT ; return GSOCK_TIMEDOUT ; } // we don't know whether a connect in progress will be issued like this if ( err != kCFSocketTimeout && socket->m_non_blocking ) { socket->m_establishing = true; socket->m_error = GSOCK_WOULDBLOCK; return GSOCK_WOULDBLOCK; } GSocket_close(socket); socket->m_error = GSOCK_IOERR; return GSOCK_IOERR; } return GSOCK_NOERROR;}/* Flags *//* GSocket_SetNonBlocking: * Sets the socket to non-blocking mode. * All IO calls will return immediately. */void GSocket_SetNonBlocking(GSocket *socket, int non_block){ assert( socket != NULL );// GSocket_Debug( ("GSocket_SetNonBlocking: %d\n", (int)non_block) ); socket->m_non_blocking = non_block;}/* * GSocket_SetTimeout: * Sets the timeout for blocking calls. Time is expressed in * milliseconds. */void GSocket_SetTimeout(GSocket *socket, unsigned long millisec){ assert( socket != NULL ); socket->m_timeout = millisec;}/* GSocket_GetError: * Returns the last error which occurred for this socket. Note that successful * operations do not clear this back to GSOCK_NOERROR, so use it only * after an error. */GSocketError GSocket_GetError(GSocket *socket){ assert( socket != NULL ); return socket->m_error;}/* Callbacks *//* GSOCK_INPUT: * There is data to be read in the input buffer. If, after a read * operation, there is still data available, the callback function will * be called again. * GSOCK_OUTPUT: * The socket is available for writing. That is, the next write call * won't block. This event is generated only once, when the connection is * first established, and then only if a call failed with GSOCK_WOULDBLOCK, * when the output buffer empties again. This means that the app should * assume that it can write since the first OUTPUT event, and no more * OUTPUT events will be generated unless an error occurs. * GSOCK_CONNECTION: * Connection successfully established, for client sockets, or incoming * client connection, for server sockets. Wait for this event (also watch * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call. * GSOCK_LOST: * The connection is lost (or a connection request failed); this could * be due to a failure, or due to the peer closing it gracefully. *//* GSocket_SetCallback: * Enables the callbacks specified by 'flags'. Note that 'flags' * may be a combination of flags OR'ed toghether, so the same * callback function can be made to accept different events. * The callback function must have the following prototype: * * void function(GSocket *socket, GSocketEvent event, char *cdata) */void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags, GSocketCallback callback, char *cdata){ int count; assert( socket != NULL ); for (count = 0; count < GSOCK_MAX_EVENT; count++) { if ((flags & (1 << count)) != 0) { socket->m_cbacks[count] = callback; socket->m_data[count] = cdata; } }}/* GSocket_UnsetCallback: * Disables all callbacks specified by 'flags', which may be a * combination of flags OR'ed toghether. */void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags){ int count; assert(socket != NULL); for (count = 0; count < GSOCK_MAX_EVENT; count++) { if ((flags & (1 << count)) != 0) { socket->m_cbacks[count] = NULL; socket->m_data[count] = NULL; } }}#define CALL_CALLBACK(socket, event) { \ _GSocket_Disable(socket, event); \ if (socket->m_cbacks[event]) \ socket->m_cbacks[event](socket, event, socket->m_data[event]); \}void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event){ int c; switch (event) { case GSOCK_CONNECTION: if (socket->m_server) c = kCFSocketReadCallBack; else c = kCFSocketConnectCallBack; break; case GSOCK_LOST: case GSOCK_INPUT: c = kCFSocketReadCallBack; break; case GSOCK_OUTPUT: c = kCFSocketWriteCallBack; break; default: c = 0; } CFSocketEnableCallBacks(socket->m_cfSocket, c);}void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event){ int c; switch (event) { case GSOCK_CONNECTION: if (socket->m_server) c = kCFSocketReadCallBack; else c = kCFSocketConnectCallBack; break; case GSOCK_LOST: case GSOCK_INPUT: c = kCFSocketReadCallBack; break; case GSOCK_OUTPUT: c = kCFSocketWriteCallBack; break; default: c = 0; break; } CFSocketDisableCallBacks(socket->m_cfSocket, c);}void _GSocket_Enable(GSocket *socket, GSocketEvent event){ socket->m_detected &= ~(1 << event); _GSocket_Install_Callback(socket, event);}void _GSocket_Disable(GSocket *socket, GSocketEvent event){ socket->m_detected |= (1 << event); _GSocket_Uninstall_Callback(socket, event);}void wxMacCFSocketCallback(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void* data, void* info){ GSocket* socket = (GSocket*)info; switch (callbackType) { case kCFSocketConnectCallBack: if ( data ) { SInt32 error = *((SInt32*)data) ; CALL_CALLBACK( socket , GSOCK_LOST ) ; GSocket_Shutdown(socket); } else { CALL_CALLBACK( socket , GSOCK_CONNECTION ) ; } break; case kCFSocketReadCallBack: CALL_CALLBACK( socket , GSOCK_INPUT ) ; break; case kCFSocketWriteCallBack: CALL_CALLBACK( socket , GSOCK_OUTPUT ) ; break; default: break; // We shouldn't get here. }}int GSocket_Read(GSocket *socket, char *buffer, int size){ int ret = 0 ; assert(socket != NULL); // if ( !CFReadStreamHasBytesAvailable() ) ret = CFReadStreamRead( socket->m_readStream , (UInt8*) buffer , size ) ; return ret;}int GSocket_Write(GSocket *socket, const char *buffer, int size){ int ret; assert(socket != NULL); ret = CFWriteStreamWrite( socket->m_writeStream , (UInt8*) buffer , size ) ; return ret;}GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags){ assert( socket != NULL ); return flags & socket->m_detected;}// ==========================================================================// wxSocketModule// ==========================================================================class wxSocketModule : public wxModule{public: virtual bool OnInit() { // wxSocketBase will call GSocket_Init() itself when/if needed return true; } virtual void OnExit() { if ( wxSocketBase::IsInitialized() ) wxSocketBase::Shutdown(); }private: DECLARE_DYNAMIC_CLASS(wxSocketModule)};IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)#endif // wxUSE_SOCKETS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -