Пример #1
0
/**
 * Handles incoming data on a client connection.
 * @param socket_server Socket server
 * @param conn Client connection
 */
static void handle_connection(struct lwpb_transport_socket_server *socket_server,
        struct lwpb_socket_server_conn *conn)
{
    void *res_buf;
    size_t res_len;
    ssize_t len;
    size_t used;
    struct protocol_header_info info;
    lwpb_err_t ret;
    
    used = conn->pos - conn->buf;
    
    len = recv(conn->socket, conn->pos, conn->len - used, 0);
    if (len <= 0) {
        close_connection(socket_server, conn);
        return;
    }
    
    conn->pos += len;
    used = conn->pos - conn->buf;
    
    LWPB_DEBUG("Client(%d) received %d bytes", conn->index, len);
    
    // Try to decode the request
    ret = parse_request(conn->buf, used, &info, socket_server->server->service_list);
    if (ret != PARSE_ERR_OK)
        return;
    
    LWPB_DEBUG("Client(%d) received request header", conn->index);
    LWPB_DEBUG("type = %d, service = %p, method = %p, header_len = %d, msg_len = %d",
               info.msg_type, info.service_desc, info.method_desc,
               info.header_len, info.msg_len);
    
    if (!info.service_desc) {
        // TODO unknown service
    }
    
    if (!info.method_desc) {
        // TODO unknown method
    }
    
    // Allocate response buffer
    ret = lwpb_transport_alloc_buf(&socket_server->super, &res_buf, &res_len);
    if (ret != LWPB_ERR_OK) {
        // TODO handle memory error
    }
    
    ret = socket_server->server->call_handler(
        socket_server->server, info.method_desc,
        info.method_desc->req_desc,conn->buf + info.header_len, info.msg_len,
        info.method_desc->res_desc, res_buf, &res_len,
        socket_server->server->arg);
    
    // Send response back to server
    send_response(conn->socket, info.method_desc, res_buf, res_len);
    
    lwpb_transport_free_buf(&socket_server->super, res_buf);
}
Пример #2
0
static void handle_data(struct lwpb_transport_socket_client *socket_client)
{
    ssize_t len;
    size_t used;
    struct protocol_header_info info;
    lwpb_err_t ret;
    
    used = socket_client->pos - socket_client->buf;
    
    len = recv(socket_client->socket, socket_client->pos,
               socket_client->len - used, 0);
    if (len <= 0) {
        // Server closed connection TODO
        LWPB_FAIL("Server closed connection");
        return;
    }
    
    socket_client->pos += len;
    used = socket_client->pos - socket_client->buf;
    
    LWPB_DEBUG("Received %d bytes", len);
    
    // Try to decode the request
    ret = parse_request(socket_client->buf, used, &info, NULL);
    if (ret != PARSE_ERR_OK)
        return;
    
    LWPB_DEBUG("Received request header");
    LWPB_DEBUG("type = %d, service = %p, method = %p, header_len = %d, msg_len = %d",
               info.msg_type, info.service_desc, info.method_desc,
               info.header_len, info.msg_len);
    
    if (!info.service_desc) {
        // TODO unknown service
    }
    
    if (!info.method_desc) {
        // TODO unknown method
    }
    
    // Process response
    ret = socket_client->client->response_handler(
        socket_client->client, socket_client->last_method,
        socket_client->last_method->res_desc,
        socket_client->buf + info.header_len, info.msg_len,
        socket_client->client->arg);
    if (ret != LWPB_ERR_OK) {
        
    }
}
Пример #3
0
/**
 * Closes a client connection.
 * @param socket_server Socket server
 * @param conn Client connection
 */
static void close_connection(struct lwpb_transport_socket_server *socket_server,
                             struct lwpb_socket_server_conn *conn)
{
    LWPB_DEBUG("Client(%d) disconnected", conn->index);
    close(conn->socket);
    conn->socket = -1;
    socket_server->num_conns--;
}
Пример #4
0
/**
 * Accepts new connections on the listen socket.
 * @param socket_server Socket server
 */
static void handle_new_connection(struct lwpb_transport_socket_server *socket_server)
{
    int socket;
    struct sockaddr_storage addr;
    socklen_t len = sizeof(addr);
    char tmp[16];
    struct sockaddr_in *addr_in;
    int i;
    const char msg[] = "No more connections allowed\n";
    
    socket = accept(socket_server->socket, (struct sockaddr *) &addr, &len);
    if (socket < 0) {
        LWPB_ERR("Accepting new socket failed (errno: %d)", errno);
        return;
    }
    
    make_nonblock(socket);
    
    for (i = 0; i < LWPB_TRANSPORT_SOCKET_SERVER_CONNS; i++) {
        struct lwpb_socket_server_conn *conn = &socket_server->conns[i];
        if (conn->socket == -1) {
            addr_in = (struct sockaddr_in *) &addr;
            inet_ntop(addr.ss_family, &addr_in->sin_addr, tmp, sizeof(tmp));
            LWPB_DEBUG("Client(%d) accepted conncetion from %s", conn->index, tmp);
            conn->socket = socket;
            if (!conn->buf)
                lwpb_transport_alloc_buf(&socket_server->super, &conn->buf, &conn->len);
            conn->pos = conn->buf;
            socket_server->num_conns++;
            return;
        }
    }
    
    // No more connections allowed
    LWPB_DEBUG("No more connections allowed");
    send(socket, msg, sizeof(msg), 0);
    close(socket);
}
Пример #5
0
/**
 * Initializes the socket client transport implementation.
 * @param socket_client Socket client transport data
 * @return Returns the transport handle.
 */
lwpb_transport_t lwpb_transport_socket_client_init(
        struct lwpb_transport_socket_client *socket_client)
{
    int i;
    
    LWPB_DEBUG("Initializing socket client");
    
    lwpb_transport_init(&socket_client->super, &transport_funs);
    
    socket_client->client = NULL;
    socket_client->socket = -1;
    socket_client->buf = NULL;
    
    return &socket_client->super;
}
Пример #6
0
/**
 * Initializes the socket server transport implementation.
 * @param socket_server Socket server transport data
 * @return Returns the transport handle.
 */
lwpb_transport_t lwpb_transport_socket_server_init(
        struct lwpb_transport_socket_server *socket_server)
{
    int i;
    
    LWPB_DEBUG("Initializing socket server");
    
    lwpb_transport_init(&socket_server->super, &transport_funs);
    
    socket_server->server = NULL;
    socket_server->socket = -1;
    socket_server->num_conns = 0;
    for (i = 0; i < LWPB_TRANSPORT_SOCKET_SERVER_CONNS; i++) {
        struct lwpb_socket_server_conn *conn = &socket_server->conns[i];
        conn->index = i;
        conn->socket = -1;
        conn->buf = NULL;
    }
    
    return &socket_server->super;
}
Пример #7
0
/**
 * Opens the socket server for communication.
 * @param transport Transport handle
 * @param host Hostname or IP address (using local address if NULL)
 * @param port Port number for listen port
 * @return Returns LWPB_ERR_OK if successful.
 */
lwpb_err_t lwpb_transport_socket_server_open(lwpb_transport_t transport,
                                           const char *host, u16_t port)
{
    struct lwpb_transport_socket_server *socket_server =
        (struct lwpb_transport_socket_server *) transport;
    lwpb_err_t ret = LWPB_ERR_OK;
    int status;
    struct addrinfo hints;
    struct addrinfo *res;
    struct sockaddr_in *addr;
    char tmp[16];
    int yes = 1;
    
    if (socket_server->socket != -1) {
        LWPB_INFO("Socket server already opened");
        return LWPB_ERR_OK;
    }

    // Resolve hostname
    LWPB_DEBUG("Resolving hostname '%s'", host);
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;          // IPv4
    hints.ai_socktype = SOCK_STREAM;    // TCP stream sockets
    hints.ai_flags = AI_PASSIVE;        // Fill in the IP
    snprintf(tmp, sizeof(tmp), "%d", port);
    if ((status = getaddrinfo(host, tmp, &hints, &res)) != 0) {
        LWPB_ERR("getaddrinfo error: %s\n", gai_strerror(status));
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    addr = (struct sockaddr_in *) res->ai_addr;
    inet_ntop(res->ai_family, &addr->sin_addr, tmp, sizeof(tmp));
    
    // Create server socket
    LWPB_DEBUG("Creating server socket");
    socket_server->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (socket_server->socket == -1) {
        LWPB_ERR("Cannot create server socket");
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    
    // Reuse address if necessary
    if (setsockopt(socket_server->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
        LWPB_ERR("Cannot set SO_REUSEADDR (error: %d)", errno);
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    
    // Make non-blocking
    make_nonblock(socket_server->socket);
    
    // Bind listen socket
    LWPB_DEBUG("Binding server socket to %s:%d", tmp, port);
    if (bind(socket_server->socket, res->ai_addr, res->ai_addrlen) == -1) {
        LWPB_ERR("Cannot bind server socket (errno: %d)", errno);
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }

    // Start listening
    LWPB_DEBUG("Start listening on server socket");
    if (listen(socket_server->socket, LWPB_TRANSPORT_SOCKET_SERVER_CONNS) == -1) {
        LWPB_ERR("Cannot listen on server socket (errno: %d)", errno);
        close(socket_server->socket);
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    
out:
    freeaddrinfo(res);
    
    return ret;
}
Пример #8
0
/**
 * Opens the socket client for communication.
 * @param transport Transport handle
 * @param host Hostname or IP address (using local address if NULL)
 * @param port Port number for listen port
 * @return Returns LWPB_ERR_OK if successful.
 */
lwpb_err_t lwpb_transport_socket_client_open(lwpb_transport_t transport,
                                           const char *host, u16_t port)
{
    struct lwpb_transport_socket_client *socket_client =
        (struct lwpb_transport_socket_client *) transport;
    lwpb_err_t ret = LWPB_ERR_OK;
    int status;
    struct addrinfo hints;
    struct addrinfo *res;
    struct sockaddr_in *addr;
    char tmp[16];
    int yes = 1;
    
    if (socket_client->socket != -1) {
        LWPB_INFO("Socket client already opened");
        return LWPB_ERR_OK;
    }

    // Allocate receive buffer
    ret = lwpb_transport_alloc_buf(&socket_client->super,
                                   &socket_client->buf, &socket_client->len);
    if (ret != LWPB_ERR_OK)
        return ret;
    socket_client->pos = socket_client->buf;

    // Resolve hostname
    LWPB_DEBUG("Resolving hostname '%s'", host);
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;          // IPv4
    hints.ai_socktype = SOCK_STREAM;    // TCP stream sockets
    hints.ai_flags = AI_PASSIVE;        // Fill in the IP
    snprintf(tmp, sizeof(tmp), "%d", port);
    if ((status = getaddrinfo(host, tmp, &hints, &res)) != 0) {
        LWPB_ERR("getaddrinfo error: %s\n", gai_strerror(status));
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    addr = (struct sockaddr_in *) res->ai_addr;
    inet_ntop(res->ai_family, &addr->sin_addr, tmp, sizeof(tmp));
    
    // Create client socket
    LWPB_DEBUG("Creating client socket");
    socket_client->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (socket_client->socket == -1) {
        LWPB_ERR("Cannot create client socket");
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    
    // Reuse address if necessary
    if (setsockopt(socket_client->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
        LWPB_ERR("Cannot set SO_REUSEADDR (error: %d)", errno);
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    
    // Connect to server
    LWPB_DEBUG("Connecting to %s:%d", tmp, port);
    if (connect(socket_client->socket, res->ai_addr, res->ai_addrlen) == -1) {
        LWPB_ERR("Cannot open connection (errno: %d)", errno);
        ret = LWPB_ERR_NET_INIT;
        goto out;
    }
    
    // Make non-blocking
    make_nonblock(socket_client->socket);
    
out:
    freeaddrinfo(res);
    
    return ret;
}