Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
 }
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
bool zmq::swap_t::full ()
{
    return buffer_space () == 1;
}
Beispiel #14
0
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;
}
Beispiel #15
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;
}
Beispiel #16
0
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;
}