Пример #1
0
static void ConnectionCloseInternal(ConnectionRef conn, Boolean sayGoodbye)
    // The core of ConnectionClose.  It's called by ConnectionClose 
    // and by ConnectionOpen, if it fails for some reason.  This exists 
    // as a separate routine so that we can add the sayGoodbye parameter, 
    // which controls whether we send a goodbye packet to the server.  We 
    // need this because we should always try to say goodbye if we're called 
    // from ConnectionClose, but if we're called from ConnectionOpen we 
    // should only try to say goodbye if we successfully connected the 
    // socket.
    //
    // Regardless, the bulk of the work of this routine is done by 
    // ConnectionShutdown.  This routine exists to a) say goodbye, if 
    // necessary, and b) free the memory associated with the connection.
{
    int     junk;
    
    if (conn != NULL) {
        assert(conn->fMagic == kConnectionStateMagic);

        if ( (conn->fSockFD != -1) && sayGoodbye ) {
            PacketGoodbye   goodbye;

            InitPacketHeader(&goodbye.fHeader, kPacketTypeGoodbye, sizeof(goodbye), false);
            snprintf(goodbye.fMessage, sizeof(goodbye.fMessage), "Process %ld signing off", (long) getpid());
            
            junk = ConnectionSend(conn, &goodbye.fHeader);
            assert(junk == 0);
        }
        ConnectionShutdown(conn);
        
        free(conn);
    }
}
Пример #2
0
void AppProtocolTasks(CHANNEL_HANDLE h) {
    if (state == STATE_CLOSED) return;
    if (state == STATE_CLOSING && ByteQueueSize(&tx_queue) == 0) {
        log_printf("Finished flushing, closing the channel.");
        ConnectionCloseChannel(h);
        state = STATE_CLOSED;
        return;
    }
    UARTTasks();
    SPITasks();
    I2CTasks();
    ICSPTasks();
    if (ConnectionCanSend(h)) {
        BYTE prev = SyncInterruptLevel(1);
        const BYTE* data;
        if (bytes_out) {
            ByteQueuePull(&tx_queue, bytes_out);
            bytes_out = 0;
        }
        ByteQueuePeek(&tx_queue, &data, &bytes_out);
        if (bytes_out > 0) {
            if (bytes_out > max_packet) bytes_out = max_packet;
            ConnectionSend(h, data, bytes_out);
        }
        SyncInterruptLevel(prev);
    }
}
Пример #3
0
static void DoShout(ConnectionRef conn, const char *message)
    // Implements the "shout" command by sending a shout packet to the server. 
    // Note that this is /not/ an RPC.
    //
    // The server responds to this packet by echoing it to each registered 
    // listener.
{
    int         err;
    PacketShout request;
    
    InitPacketHeader(&request.fHeader, kPacketTypeShout, sizeof(request), false);
    snprintf(request.fMessage, sizeof(request.fMessage), "%s", message);
    
    err = ConnectionSend(conn, &request.fHeader);
    PrintResult("shout", err, message);
}
Пример #4
0
void AppProtocolTasks(CHANNEL_HANDLE h) {
  UARTTasks();
  SPITasks();
  I2CTasks();
  ICSPTasks();
  /***********************SNES/NES****************************/
  SNESTasks();
  /***********************************************************/
  if (ConnectionCanSend(h)) {
    BYTE prev = SyncInterruptLevel(1);
    const BYTE* data;
    if (bytes_out) {
      ByteQueuePull(&tx_queue, bytes_out);
      bytes_out = 0;
    }
    ByteQueuePeek(&tx_queue, &data, &bytes_out);
    if (bytes_out > 0) {
      if (bytes_out > max_packet) bytes_out = max_packet;
      ConnectionSend(h, data, bytes_out);
    }
    SyncInterruptLevel(prev);
  }
}
Пример #5
0
static int ConnectionRPC(
    ConnectionRef           conn, 
    const PacketHeader *    request, 
    PacketHeader *          reply, 
    size_t                  replySize
)
    // Perform an RPC (Remote Procedure Call) with the server.  That is, send 
    // the server a packet and wait for a reply.  You can only use this on 
    // connections that are not in listening mode.
    //
    // conn must be a valid connection
    //
    // packet must be a valid, ready-to-send, packet
    //
    // reply and replySize specify a buffer where the reply packet is placed;
    // reply size must not be NULL; replySize must not be less that the 
    // packet header size (sizeof(PacketHeader)); if the reply packet is bigger 
    // than replySize, the data that won't fit is discarded; you can detect this 
    // by looking at reply->fSize
    //
    // Returns an errno-style error code
    // On success, the buffer specified by reply and replySize will contain the 
    // reply packet; on error, the contents of that buffer is invalid; also, 
    // if this routine errors the connection is no longer useful (conn is still 
    // valid, but you can't use it to transmit any more data)
{
    int     err;
    
    assert(conn != NULL);
    assert(conn->fSockFD != -1);            // connection must not be shut down
    assert(conn->fSockCF == NULL);          // RPC and listening are mutually exclusive
                                            // because unsolicited packet might get mixed up 
                                            // with the reply

    assert(request != NULL);
    assert(request->fMagic == kPacketMagic);
    assert(request->fSize >= sizeof(PacketHeader));

    assert(reply != NULL);
    assert(replySize >= sizeof(PacketHeader));
    
    // Send the request.
    
    err = ConnectionSend(conn, request);
    
    // Read and validate the reply header.
    
    if (err == 0) {
        err = MoreUNIXRead(conn->fSockFD, reply, sizeof(PacketHeader), NULL);
    }
    if ( (err == 0) && (reply->fMagic != kPacketMagic) ) {
        fprintf(stderr, "ConnectionRPC: Bad magic (%.4s).\n", (char *) &reply->fMagic);
        err = EINVAL;
    }
    if ( (err == 0) && (reply->fType != kPacketTypeReply) ) {
        fprintf(stderr, "ConnectionRPC: Type wrong (%.4s).\n", (char *) &reply->fType);
        err = EINVAL;
    }
    if ( (err == 0) && (reply->fID != request->fID) ) {
        fprintf(stderr, "ConnectionRPC: ID mismatch (%" PRId32 ").\n", reply->fID);
        err = EINVAL;
    }
    if ( (err == 0) && ( (reply->fSize < sizeof(PacketHeader)) || (reply->fSize > kPacketMaximumSize) ) ) {
        fprintf(stderr, "ConnectionRPC: Bogus packet size (%" PRIu32 ").\n", reply->fSize);
        err = EINVAL;
    }

    // Read the packet payload that will fit in the reply buffer.
    
    if ( (err == 0) && (reply->fSize > sizeof(PacketHeader)) ) {
        uint32_t  payloadToRead;
        
        if (reply->fSize > replySize) {
            payloadToRead = replySize;
        } else {
            payloadToRead = reply->fSize;
        }
        payloadToRead -= sizeof(PacketHeader);
        
        err = MoreUNIXRead(conn->fSockFD, ((char *) reply) + sizeof(PacketHeader), payloadToRead, NULL);
    }

    // Discard any remaining packet payload that will fit in the reply buffer.
    // The addition check in the next line is necessary to avoid the undefined behaviour 
    // of malloc(0) in the dependent block.

    if ( (err == 0) && (reply->fSize > replySize) ) {
        uint32_t    payloadToJunk;
        void *      junkBuf;
        
        payloadToJunk = reply->fSize - replySize;
        
        junkBuf = malloc(payloadToJunk);
        if (junkBuf == NULL) {
            err = ENOMEM;
        }
        
        if (err == 0) { 
            err = MoreUNIXRead(conn->fSockFD, junkBuf, payloadToJunk, NULL);
        }
        
        free(junkBuf);
    }

    // Any errors cause us to immediately shut down our connection because we 
    // we're no longer sure of the state of the channel (that is, did we leave 
    // half a packet stuck in the pipe).
    
    if (err != 0) {
        ConnectionShutdown(conn);
    }
    
    return err;
}
Пример #6
0
int ClientHandlerPrivmsg(PCLIENT pClient, char* strCommand, char* strParams)
{
  if(CompareIRCAddressNick(strParams,c_strBouncerName))
  {
    char *strAction,*str;

    pClient->cMessageMode = CMM_PRIVMSG;

    strAction = strParams+strlen(c_strBouncerName)+1;
    if(*strAction == ':')
      strAction++;

    str = strAction;
    do
    {
      if(*str == ' ')
      {
        *(str++) = '\0';
        break;
      }
      else if(*str == '\r' || *str == '\n')
      {
        *str = '\0';
        break;
      }
      *str = toupper(*str);
      ++str;
    } while(*str);
    
    {
      struct tagCLIENTHANDLER* pHandler;
      HASH_LOOKUP(CLIENTHANDLER_HASH,g_hashClientHandlers,strAction,pHandler);
      if(pHandler && ( 
        !(pHandler->nFlags & CHF_BOUNCER) ||
        (!(pHandler->nFlags & CHF_ADMIN) && (!pClient->pUser->strAllowedCommands || !ConfigFindVar(pClient->pUser->strAllowedCommands,pHandler->strAction))) ||
        (pHandler->nFlags & CHF_ADMIN && !pClient->bAdmin) ) )
        pHandler = 0;
      if(pHandler)
      {
        sprintf(strCommand,"msg %s %s",c_strBouncerName,pHandler->strAction);
        pHandler->pProc(pClient,strCommand,str);
      }
      else
        ClientMessage(pClient,"Unknown command \"%s\"\r\n",strAction);
    }

    pClient->cMessageMode = CMM_DEFAULT;
    return 1;
  }

  {
    char* strArg[2];
    if(SplitIRCParams(strParams,strArg,sizeof(strArg)/sizeof(*strArg),1) == sizeof(strArg)/sizeof(*strArg))
    {
      if(pClient->pProfile)
      {
        PPROFILE pProfile = pClient->pProfile;
        PPROFILECHANNEL pProfileChannel;

        HASHLIST_LOOKUP(PROFILE_PROFILECHANNEL_HASHLIST,pProfile->hashlistProfileChannels,strArg[0],pProfileChannel);
        if(pProfileChannel)
        {
          PCLIENT pCurClient;
          unsigned short sLength;

          sLength = strformat(g_strOutBuffer,sizeof(g_strOutBuffer),":%s!~%s@%s PRIVMSG %s :%s\r\n",pClient->strNick,pClient->pUser->strName,iptoa(pClient->pConnection->nIP),strArg[0],strArg[1]);

          for(pCurClient = pProfile->listClients.pFirst; pCurClient; pCurClient = pCurClient->llProfile.pNext)
            if(pCurClient != pClient)
              ConnectionSend(pCurClient->pConnection,g_strOutBuffer,sLength);

          ProfileLogMsgCreate(0,pProfileChannel,++pProfile->nLogID,g_strOutBuffer,sLength,PLMF_TIMESTAMP|PLMF_ADJUSTNICKLEN);
        }
      }
    }
  }

  return 0;
}