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); } }
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); } }
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); }
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); } }
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; }
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; }