static void ws_event_cb(evbev_t *bev, short what, void *args) { wshtp_conn_t *conn = args; bufferevent_lock(bev); if (what & BEV_EVENT_EOF || what & BEV_EVENT_ERROR || what & BEV_EVENT_TIMEOUT) { conn->method = WSHTP_ON_CLOSE; bufferevent_unlock(bev); wshtp_hooks_call(conn->server, conn->method, conn); bufferevent_lock(bev); } bufferevent_unlock(bev); }
int MTCLink::SendPacket(SBCPacket *packet) { packet->numBytes = packet->header.numberBytesinPayload + sizeof(uint32_t) + sizeof(SBCHeader) + kSBC_MaxMessageSizeBytes; int numBytesToSend = packet->numBytes; bufferevent_lock(fBev); bufferevent_write(fBev,packet,numBytesToSend); bufferevent_unlock(fBev); return 0; }
/** * Event handler for monitor connection. * @param[in] bev * @param[in] events * @param[in] ctx */ static void zmonitor_event_cb(struct bufferevent *bev, short events, void *ctx) { struct zmonitor_conn *conn = (struct zmonitor_conn *) ctx; if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { bufferevent_unlock(bev); zmonitor_conn_deactivate(conn); bufferevent_lock(bev); zmonitor_conn_free(conn); } }
int MTCLink::SendXilinxPacket(SBCPacket *packet, int waitSeconds) { int numBytesToSend = packet->numBytes; bufferevent_lock(fBev); bufferevent_write(fBev,packet,numBytesToSend); bufferevent_unlock(fBev); int bytesRecved = 0; while (true){ pthread_mutex_lock(&fRecvQueueLock); if (waitSeconds){ struct timeval tp; struct timespec ts; gettimeofday(&tp, NULL); ts.tv_sec = tp.tv_sec; ts.tv_nsec = tp.tv_usec * 1000; ts.tv_sec += waitSeconds; while (fRecvQueue.empty()){ int rc = pthread_cond_timedwait(&fRecvQueueCond,&fRecvQueueLock,&ts); if (rc == ETIMEDOUT) { lprintf("MTCLink::SendXilinxPacket: Wait timed out!\n"); rc = pthread_mutex_unlock(&fRecvQueueLock); return 1; } } }else{ while (fRecvQueue.empty()) pthread_cond_wait(&fRecvQueueCond,&fRecvQueueLock); } *packet = fRecvQueue.front(); fRecvQueue.pop(); bytesRecved += packet->numBytes; pthread_mutex_unlock(&fRecvQueueLock); if (bytesRecved >= numBytesToSend) break; } return 0; }
void TierClientConnectionWriteCB(TierClientConnectionRef me){ if(me->doQuitGracefully) return; if(me->clearToSend == YES) { OCSerializerRef s = OCSerializerCreate(); ALChunkRef chunk = NULL; while( (chunk=(ALChunkRef)OCListFifoPop(me->toSendChunks)) != NULL) { OCSerializerReset(s); ALChunkSerialize(chunk, s); size_t nBytes = OCSerializerGetNumberOfBytes(s); if(nBytes < TIER_MESSAGE_MAX_LENGTH) { struct TierMessage msg; msg.header.messageType = TMCHUNK; msg.header.protocolVariant = 0; msg.header.protocolVersion = 0; msg.header.dataLength = OCSerializerGetNumberOfBytes(s); OCSerializerCopyBytes(s, msg.data); bufferevent_lock(me->be); TierMessageWriteToEVBuffer(&msg, me->be->output); bufferevent_write_buffer(me->be, bufferevent_get_output(me->be)); bufferevent_unlock(me->be); OCListFifoPush(me->unackedChunks, (OCObjectRef)chunk); } // OCListFifoPop does not release the chunk, we have to do this: OCObjectRelease(&chunk); } OCObjectRelease(&s); me->clearToSend = NO; } me->clearToSend = YES; }
void MTCLink::RecvCallback(struct bufferevent *bev) { int totalLength = 0; int n; char input[10000]; memset(input,'\0',10000); while (1){ bufferevent_lock(bev); n = bufferevent_read(bev, input+strlen(input), sizeof(input)); bufferevent_unlock(bev); totalLength += n; if (n <= 0) break; } char *inputP = input; while (totalLength > 0){ if (fTempBytes == 0){ int numThisPacket = ((SBCPacket *) inputP)->numBytes; if (numThisPacket > totalLength){ memcpy(fTempPacket,inputP,totalLength); fBytesLeft = numThisPacket-totalLength; fTempBytes = totalLength; break; }else{ memcpy(fTempPacket,inputP,numThisPacket); SBCPacket *packet = (SBCPacket *) fTempPacket; pthread_mutex_lock(&fRecvQueueLock); fRecvQueue.push(*packet); //lprintf("Got packet, size %d empty %d\n",fRecvQueue.size(),fRecvQueue.empty()); pthread_cond_signal(&fRecvQueueCond); pthread_mutex_unlock(&fRecvQueueLock); memset(fTempPacket,0,sizeof(fTempPacket)); totalLength -= numThisPacket; inputP += numThisPacket; } }else{ if (fBytesLeft > totalLength){ memcpy(fTempPacket+fTempBytes,inputP,totalLength); fBytesLeft -= totalLength; fTempBytes += totalLength; break; }else{ memcpy(fTempPacket+fTempBytes,inputP,fBytesLeft); SBCPacket *packet = (SBCPacket *) fTempPacket; pthread_mutex_lock(&fRecvQueueLock); fRecvQueue.push(*packet); //lprintf("Got packet, size %d empty %d\n",fRecvQueue.size(),fRecvQueue.empty()); pthread_cond_signal(&fRecvQueueCond); pthread_mutex_unlock(&fRecvQueueLock); memset(fTempPacket,0,sizeof(fTempPacket)); inputP += fBytesLeft; totalLength -= fBytesLeft; fBytesLeft = 0; fTempBytes = 0; } } } // if (fTempBytes) // lprintf("%d bytes left\n",fBytesLeft); }
static int ws_send_frame(wshtp_conn_t *conn, bool fin, uint8_t opcode, const void *data, size_t size, bool mask, uint32_t mask_key) { uint8_t byte0 = opcode; if (fin) { byte0 |= FIN; } uint8_t byte1 = 0; // maks_flag(1 bit) + payload_len(7 bits) size_t frame_size = 2; union { uint16_t len_16; uint64_t len_64; char bytes[8]; } ext_payload_len; if (size > INT16_MAX) { byte1 = 127; frame_size += 8; ext_payload_len.len_64 = (uint64_t)size; }else if (size > 125) { byte1 = 126; frame_size += 2; ext_payload_len.len_16 = (uint16_t)size; }else { byte1 = (uint8_t)size; } if (mask) { frame_size += 4; byte1 |= MASK; //set mask } frame_size += size; char *frame_data = (char *)calloc(frame_size, sizeof(char)); //allocate frame data int index = 0; frame_data[index++] = byte0; frame_data[index++] = byte1; //SET extended payload_len if required if (size > INT16_MAX) { frame_data[index++] = ext_payload_len.bytes[7]; frame_data[index++] = ext_payload_len.bytes[6]; frame_data[index++] = ext_payload_len.bytes[5]; frame_data[index++] = ext_payload_len.bytes[4]; frame_data[index++] = ext_payload_len.bytes[3]; frame_data[index++] = ext_payload_len.bytes[2]; frame_data[index++] = ext_payload_len.bytes[1]; frame_data[index++] = ext_payload_len.bytes[0]; } else if (size > 125) { frame_data[index++] = ext_payload_len.bytes[1]; frame_data[index++] = ext_payload_len.bytes[0]; } //SET mask_key if MASK is set if (mask) { int32_t *i32 = (int32_t*)&frame_data[index]; *i32 = mask_key; index += 4; } memcpy(&frame_data[index], data, size); evbev_t *bev =evhtp_connection_get_bev(conn->conn); evbuf_t *reply_buf = conn->conn->scratch_buf; evbuffer_drain(reply_buf, -1); evbuffer_add(reply_buf, &frame_data[0], frame_size); bufferevent_lock(bev); { bufferevent_write_buffer(bev, reply_buf); } bufferevent_unlock(bev); evbuffer_drain(reply_buf, -1); free(frame_data); return 0; }
static void ws_read_cb(evbev_t * bev, void *arg) { size_t data_len = 0; wshtp_conn_t *conn = (wshtp_conn_t*)arg; evbuf_t *in = bufferevent_get_input(bev); bufferevent_lock(bev); while ( (data_len = evbuffer_get_length(in)) ){ void *data = evbuffer_pullup(in, data_len); ws_frame_t frame; size_t nread = ws_parse_frame(data, data_len, &frame); if (frame.status == STATUS_OK) { if (frame.opcode == OP_TEXT) { conn->data.type = WS_DATA_TEXT; conn->method = WSHTP_ON_MESSAGE; } else if (frame.opcode == OP_BIN) { conn->data.type = WS_DATA_BINARY; conn->method = WSHTP_ON_MESSAGE; } else if (frame.opcode == OP_CLOSE) { conn->method = WSHTP_ON_CLOSE; } if (frame.fin == 0 || frame.opcode == OP_CONT) { if (conn->data.ws_frames == NULL) { conn->data.ws_frames = ws_buffer_new(); } ws_buffer_append_data(conn->data.ws_frames, frame.data, frame.payload_len); } if (conn->method == WSHTP_ON_CLOSE) { evbuffer_drain(in, data_len); } else { evbuffer_drain(in, nread); } if (frame.fin) { if (conn->data.ws_frames) { conn->data.content = ws_buffer_get_data(conn->data.ws_frames, &conn->data.size); ws_buffer_free(conn->data.ws_frames); conn->data.ws_frames = NULL; } else { conn->data.content = frame.data; conn->data.size = frame.payload_len; } bufferevent_unlock(bev); wshtp_hooks_call(conn->server, conn->method, conn); bufferevent_lock(bev); free(conn->data.content); conn->data.content = NULL; conn->data.size = 0; } } else { break; } } // free fragments bufferevent_unlock(bev); }
void MessageManager::MessageDispatcher(struct bufferevent *bev, void *ctx) { bufferevent_lock(bev); struct evbuffer *input = bufferevent_get_input(bev); evutil_socket_t socketFD = bufferevent_getfd(bev); uint32_t length = 0, evbufferLength; bool keepGoing = true; while(keepGoing) { evbufferLength = evbuffer_get_length(input); //If we don't even have enough data to read the length, just quit if(evbufferLength < sizeof(length)) { keepGoing = false; continue; } //Copy the length field out of the message // We only want to copy this data at first, because if the whole message hasn't reached us, // we'll want the whole buffer still present here, undrained if(evbuffer_copyout(input, &length, sizeof(length)) != sizeof(length)) { keepGoing = false; continue; } // Make sure the length appears valid // TODO: Assign some arbitrary max message size to avoid filling up memory by accident if(length < MESSAGE_MIN_SIZE) { LOG(WARNING, "Error parsing message: message too small.", ""); evbuffer_drain(input, sizeof(length)); keepGoing = false; continue; } //If we don't yet have enough data, then just quit and wait for more if(evbufferLength < length) { keepGoing = false; continue; } evbuffer_drain(input, sizeof(length)); //Remove the length of the "length" variable itself length -= sizeof(length); char *buffer = (char*)malloc(length); if(buffer == NULL) { // This should never happen. If it does, probably because length is an absurd value (or we're out of memory) LOG(WARNING, "Error parsing message: malloc returned NULL. Out of memory?.", ""); free(buffer); keepGoing = false; continue; } // Read in the actual message int bytesRead = evbuffer_remove(input, buffer, length); if(bytesRead == -1) { LOG(WARNING, "Error parsing message: couldn't remove data from buffer.", ""); } else if((uint32_t)bytesRead != length) { LOG(WARNING, "Error parsing message: incorrect amount of data received than what expected.", ""); } MessageEndpointLock endpoint = MessageManager::Instance().GetEndpoint(socketFD); if(endpoint.m_endpoint != NULL) { Message *message = Message::Deserialize(buffer, length); if(!endpoint.m_endpoint->PushMessage(message)) { LOG(DEBUG, "Discarding message. Error in pushing it to a queue.", ""); } } else { LOG(DEBUG, "Discarding message. Received it for a non-existent endpoint.", ""); } free(buffer); } bufferevent_unlock(bev); }