transition_result_t handle_data_begin(context_t *context) { if (context->is_wait_transition) { switch (transaction_add_data_status(&context->transaction)) { case TRANSACTION_DONE: context->is_wait_transition = 0; if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "354 Start mail input; end with <CRLF>.<CRLF>" CRLF) < 0) { return TRANSITION_ERROR; } return TRANSITION_SUCCEED; case TRANSACTION_WAIT: return TRANSITION_WAIT; default: return TRANSITION_ERROR; } } if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } if (transaction_add_header(&context->transaction) < 0) { return TRANSITION_ERROR; } context->is_wait_transition = 1; return TRANSITION_WAIT; }
transition_result_t handle_data_end(context_t *context) { switch (transaction_commit(&context->transaction)) { case TRANSACTION_DONE: break; case TRANSACTION_WAIT: context->is_wait_transition = 1; return TRANSITION_WAIT; default: return TRANSITION_ERROR; } context->is_wait_transition = 0; if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "250 Ok" CRLF) < 0) { return TRANSITION_ERROR; } log_write(context->log, "[%s] commit transaction, file saved: %s", context->uuid, context->transaction.__data_filename); return TRANSITION_SUCCEED; }
bool zmq::swap_t::fits (zmq_msg_t *msg_) { // Check whether whole binary representation of the message // fits into the swap. size_t msg_size = zmq_msg_size (msg_); if (buffer_space () <= (int64_t) (sizeof msg_size + 1 + msg_size)) return false; return true; }
int buffer_pull(Buffer b, int fd){ int len; buffer_normalize(b); len = read(fd, b->buf + b->end, buffer_space(b)); if(len > 0) b->end += len; buffer_normalize(b); return len; }
transition_result_t handle_vrfy(context_t *context) { if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "502 Command not implemented" CRLF) < 0) { return TRANSITION_ERROR; } return TRANSITION_SUCCEED; }
transition_result_t handle_invalid(context_t *context) { if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "451 Requested action aborted: internal error" CRLF) < 0) { return TRANSITION_ERROR; } return TRANSITION_SUCCEED; }
transition_result_t handle_quit(context_t *context) { if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "221 Service closing transmission channel" CRLF) < 0) { return TRANSITION_ERROR; } return TRANSITION_SUCCEED; }
int buffer_add(Buffer b, const char *data, int sz){ int after = buffer_space(b); int before = (b->start > b->end ? 0 : b->start); buffer_normalize(b); if(sz > after + before) return after + before - sz; if(sz > after){ memcpy(b->buf + b->end, data, after); memcpy(b->buf, data, sz - after); }else{ memcpy(b->buf + b->end, data, sz); } b->end += sz; buffer_normalize(b); return sz; }
transition_result_t handle_mail(context_t *context) { buffer_t *in_buf = &context->in_message; size_t reverse_path_length; const char *reverse_path = parse_mail(in_buf, &reverse_path_length); if (NULL == reverse_path) { if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "555 Syntax error in reverse-path or not present" CRLF) < 0) { return TRANSITION_ERROR; } return TRANSITION_FAILED; } if (transaction_begin(&context->transaction) < 0) { return TRANSITION_ERROR; } if (transaction_set_reverse_path(&context->transaction, reverse_path, reverse_path_length) < 0) { CALL_ERR("transaction_set_reverse_path"); return TRANSITION_ERROR; } if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "250 Ok" CRLF) < 0) { return TRANSITION_ERROR; } log_write(context->log, "[%s] begin transaction", context->uuid); return TRANSITION_SUCCEED; }
bool zmq::swap_t::store (zmq_msg_t *msg_) { size_t msg_size = zmq_msg_size (msg_); // Check buffer space availability. // NOTE: We always keep one byte open. if (buffer_space () <= (int64_t) (sizeof msg_size + 1 + msg_size)) return false; // Don't store the ZMQ_MSG_SHARED flag. uint8_t msg_flags = msg_->flags & ~ZMQ_MSG_SHARED; // Write message length, flags, and message body. copy_to_file (&msg_size, sizeof msg_size); copy_to_file (&msg_flags, sizeof msg_flags); copy_to_file (zmq_msg_data (msg_), msg_size); zmq_msg_close (msg_); return true; }
transition_result_t handle_rcpt(context_t *context) { buffer_t *in_buf = &context->in_message; size_t forward_path_length; const char *forward_path = parse_rcpt(in_buf, &forward_path_length); if (NULL == forward_path) { if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "555 Syntax error in forward-path or not present" CRLF) < 0) { return TRANSITION_ERROR; } return TRANSITION_FAILED; } if (transaction_add_forward_path(&context->transaction, forward_path, forward_path_length) < 0) { CALL_ERR("transaction_add_forward_path"); return TRANSITION_ERROR; } if (buffer_shift_read_after(&context->in_message, CRLF, sizeof(CRLF) - 1) < 0) { return TRANSITION_ERROR; } if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } if (BUFFER_TAILQ_PUSH_BACK_STRING(&context->out_message_queue, "250 Ok" CRLF) < 0) { return TRANSITION_ERROR; } return TRANSITION_SUCCEED; }
transition_result_t handle_data(context_t *context) { buffer_t *in_buf = &context->in_message; if (context->is_wait_transition) { switch (transaction_add_data_status(&context->transaction)) { case TRANSACTION_DONE: if (buffer_space(&context->in_message) == 0) { buffer_drop_read(&context->in_message); } context->is_wait_transition = 0; return TRANSITION_SUCCEED; case TRANSACTION_WAIT: return TRANSITION_WAIT; default: return TRANSITION_ERROR; } } const char *begin = buffer_find(in_buf, CRLF, sizeof(CRLF) - 1); if (begin == buffer_end(in_buf)) { return TRANSITION_ERROR; } const char *data = buffer_read_begin(in_buf); const size_t data_size = begin - data + sizeof(CRLF) - 1; if (transaction_add_data(&context->transaction, data, data_size) != data_size) { return TRANSITION_ERROR; } buffer_shift_read(in_buf, data_size); context->is_wait_transition = 1; return TRANSITION_WAIT; }
bool zmq::swap_t::full () { return buffer_space () == 1; }
void text_buffer_print_wrap(text_buffer *text, const char *data, int wrapcol) { INT32 stopcol = (wrapcol < MAX_LINE_LENGTH) ? wrapcol : MAX_LINE_LENGTH; INT32 needed_space; /* we need to ensure there is enough space for this string plus enough for the max line length */ needed_space = (INT32)strlen(data) + MAX_LINE_LENGTH; /* make space in the buffer if we need to */ while (buffer_space(text) < needed_space && text->linestart != text->lineend) { text->linestartseq++; if (++text->linestart >= text->linesize) text->linestart = 0; text->bufstart = text->lineoffs[text->linestart]; } /* now add the data */ for ( ; *data; data++) { int ch = *data; int linelen; /* a CR resets our position */ if (ch == '\r') text->bufend = text->lineoffs[text->lineend]; /* non-CR data is just characters */ else if (ch != '\n') text->buffer[text->bufend++] = ch; /* an explicit newline or line-too-long condition inserts a newline */ linelen = text->bufend - text->lineoffs[text->lineend]; if (ch == '\n' || linelen >= stopcol) { int overflow = 0; /* if we're wrapping, back off until we hit a space */ if (linelen >= wrapcol) { /* scan backwards, removing characters along the way */ overflow = 1; while (overflow < linelen && text->buffer[text->bufend - overflow] != ' ') overflow++; /* if we found a space, take it; otherwise, reset and pretend we didn't try */ if (overflow < linelen) linelen -= overflow; else overflow = 0; } /* did we beat the max width */ if (linelen > text->maxwidth) text->maxwidth = linelen; /* append a terminator */ if (overflow == 0) text->buffer[text->bufend++] = 0; else text->buffer[text->bufend - overflow] = 0; /* determine what the next line will be */ if (++text->lineend >= text->linesize) text->lineend = 0; /* if we're out of lines, consume the next one */ if (text->lineend == text->linestart) { text->linestartseq++; if (++text->linestart >= text->linesize) text->linestart = 0; text->bufstart = text->lineoffs[text->linestart]; } /* if we don't have enough room in the buffer for a max line, wrap to the start */ if (text->bufend + MAX_LINE_LENGTH + 1 >= text->bufsize) text->bufend = 0; /* create a new empty line */ text->lineoffs[text->lineend] = text->bufend - (overflow ? (overflow - 1) : 0); } } /* NULL terminate what we have on this line */ text->buffer[text->bufend] = 0; }
static void * usock_read_handler(void *data) { USocket *usock = (USocket *)data; sem_wait(&usock->sem); while (!(usock->status & USOCK_CLOSE)) { umsg_t umsg; if (recv_umsg(usock, &umsg, tbuf, MAX_MTU) < 0) goto err; switch (umsg.mtype) { case UMSG_PACK: { Uint32 mcount = htonl(umsg.mcount); Uint32 mtype; pthread_mutex_lock(&usock->rlock); if (umsg.mcount > usock->r_pack_count) { if (umsg.mcount > usock->r_pack_count + 1) goto err; if (buffer_space(usock->rbuf) < umsg.mlen) { usock->tsize = umsg.mlen; memcpy(usock->tbuf, tbuf, umsg.mlen); } else { buffer_write(usock->rbuf, tbuf, umsg.mlen); } usock->r_pack_count = umsg.mcount; } pthread_mutex_unlock(&usock->rlock); pthread_cond_signal(&usock->rcond); if (usock->tsize > 0) mtype = UMSG_BUSY; else mtype = UMSG_PACK_COUNT; if (send_umsg(usock, mtype, &mcount, sizeof(mcount)) < 0) goto err; continue; } case UMSG_PACK_COUNT: { int mcount = ntohl(*(Uint32 *)tbuf); //printf("UMSG_PACK_COUNT:%d %d\n", mcount, usock->w_pack_count); if (mcount == usock->w_pack_count) pthread_cond_signal(&usock->wcond); continue; } case UMSG_BUSY: { int mcount = ntohl(*(Uint32 *)tbuf); //printf("UMSG_BUSY:%d %d\n", mcount, usock->w_pack_count); if (mcount == usock->w_pack_count) { usock->status |= USOCK_PEER_BUSY; pthread_cond_signal(&usock->wcond); } continue; } case UMSG_CONT: { Uint32 mcount = ntohl(*(Uint32 *)tbuf); if (send_umsg(usock, UMSG_REPLY_CONT, tbuf, sizeof(mcount)) < 0) goto err; if (mcount == usock->w_pack_count) { if (usock->status & USOCK_PEER_BUSY) { usock->status &= ~USOCK_PEER_BUSY; pthread_cond_signal(&usock->wcond); } } continue; } case UMSG_REPLY_CONT: { Uint32 mcount = ntohl(*(Uint32 *)tbuf); //printf("UMSG_REPLY_CONT:%d %d\n", mcount, usock->w_pack_count); if (mcount == usock->r_pack_count) pthread_cond_signal(&usock->rcond); continue; } case UMSG_CLOSE: send_umsg(usock, UMSG_REPLY_CLOSE, NULL, 0); usock->status &= ~USOCK_CONNECT; pthread_cond_broadcast(&usock->rcond); goto err; case UMSG_REPLY_CLOSE: pthread_cond_broadcast(&usock->wcond); goto err; default: continue; } } err: pthread_mutex_unlock(&usock->rlock); sem_post(&usock->sem); return NULL; }
int main(int argc, char *argv[]) { struct pollfd fds[1]; if (!argv[1]) { printf("Usage: ./client <port_number>\n"); return -1; } int sockfd; int len, port; struct sockaddr_in address; int result = 0; char buffer[512] = { 0 }; port = atoi(argv[1]); sockfd = socket(AF_INET, SOCK_STREAM, 0); //if ( setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &yes, sizeof(int)) == -1 ) //{ //perror("setsockopt"); //} address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr("127.0.0.1"); address.sin_port = htons(port); len = sizeof(address); int i = 0, j = 0, ret = 0; int flags = 0; //fcntl(sockfd, F_SETFL, O_NONBLOCK); uint8_t buff[255] = { 0 }; uint8_t parse_buffer[255] = { 0 }; circular_buffer_t c_buffer; buffer_init(&c_buffer, 255); //const char * data = "Hello there."; //const char * data1 = "Goodbye."; if (connect(sockfd, (struct sockaddr *) &address, len) == -1) { perror("oops: client failed to connect"); } fds[0].fd = sockfd; fds[0].events = POLLIN; fds[0].revents = 0; while (1) { sleep(2); int num_bytes = buffer_space(&c_buffer); //printf("Space available within the buffer: %d\n",num_bytes); result = read(sockfd, buffer, num_bytes); //printf("Result: %d\n",result); buffer_write(&c_buffer, buffer, result); //buffer_print(&c_buffer); //Clear the temporary buffer memset(buffer, '\0', 255); memset(parse_buffer, '\0', 255); result = buffer_read(&c_buffer, parse_buffer, 255); //Try to create a linear buffer for parsing. //printf("\nParse buffer [START]\n"); //for(j=0; j < 255; j++) // printf("%c",parse_buffer[j]); //printf("\nParse buffer [END]\n"); //Parse it! uint8_t *pch = NULL; int index = 0, start = 0; int bytes_occupied = 0; for (index = 0; index < 255; index++) { if (parse_buffer[index] == '\n') { bytes_occupied = index - start; bytes_occupied++; //printf("bytes_occupied: %d\n",bytes_occupied); //Process message, simply print it in this case printf("\nMessage received: "); for (j = start; j < index; j++) printf("%c", parse_buffer[j]); printf("\n"); //Message finished with, move on start = index + 1; //Remove this number of bytes (the message) from the buffer ret = buffer_consume(&c_buffer, bytes_occupied); //printf("Buffer_consume (%d): %d\n", bytes_occupied,ret); //buffer_print(&c_buffer); } } //buffer_print(&c_buffer); //return 0; //Temp } buffer_reset(&c_buffer); close(sockfd); return 0; }