⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfsocket.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:
  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 + -