📄 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 + -