GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/message.c Lines: 0 82 0.0 %
Date: 2020-12-10 21:44:00 Branches: 0 30 0.0 %

Line Branch Exec Source
1
#include "message.h"
2
#include "server.h"
3
#include "worker.h"
4
#include "ringbuf.h"
5
#include "session.h"
6
#include "event.h"
7
#include "str.h"
8
#include "log.h"
9
#include "alloc.h"
10
#include "error.h"
11
#include "predict.h"
12
13
#include <time.h>
14
15
void WSS_message_send_frames(void *serv, void *sess, wss_frame_t **frames, size_t frames_count) {
16
    size_t j, k;
17
    ssize_t off;
18
    char *out;
19
    uint64_t out_length;
20
    wss_message_t *m;
21
    ringbuf_worker_t *w = NULL;
22
    struct timespec tim;
23
    wss_server_t *server = (wss_server_t *)serv;
24
    wss_session_t *session = (wss_session_t *)sess;
25
26
    // Use extensions
27
    if ( NULL != session->header->ws_extensions ) {
28
        for (j = 0; likely(j < session->header->ws_extensions_count); j++) {
29
            session->header->ws_extensions[j]->ext->outframes(
30
                    session->fd,
31
                    frames,
32
                    frames_count);
33
34
            for (k = 0; likely(k < frames_count); k++) {
35
                session->header->ws_extensions[j]->ext->outframe(session->fd, frames[k]);
36
            }
37
        }
38
    }
39
40
    if ( unlikely((out_length = WSS_stringify_frames(frames, frames_count, &out)) == 0) ) {
41
        WSS_log_error("Unable to convert frames to message");
42
43
        return;
44
    }
45
46
    if ( unlikely(NULL == (m = WSS_malloc(sizeof(wss_message_t)))) ) {
47
        WSS_log_error("Unable to allocate message structure");
48
49
        WSS_free((void **) &out);
50
51
        return;
52
    }
53
    m->msg = out;
54
    m->length = out_length;
55
    m->framed = true;
56
57
    WSS_log_trace("Putting message into ringbuffer");
58
59
    if ( unlikely(-1 == (off = ringbuf_acquire(session->ringbuf, &w, 1))) ) {
60
        WSS_log_error("Failed to acquire space in ringbuffer");
61
62
        WSS_message_free(m);
63
64
        return;
65
    }
66
67
    session->messages[off] = m;
68
    ringbuf_produce(session->ringbuf, &w);
69
    tim.tv_sec = 0;
70
    tim.tv_nsec = 100000000;
71
72
    do {
73
        pthread_mutex_lock(&session->lock);
74
75
        switch (session->state) {
76
        case READING:
77
            pthread_mutex_unlock(&session->lock);
78
            nanosleep(&tim, NULL);
79
            break;
80
        case CLOSING:
81
            WSS_session_jobs_dec(session);
82
            pthread_mutex_unlock(&session->lock);
83
            return;
84
        case CONNECTING:
85
            pthread_mutex_unlock(&session->lock);
86
            nanosleep(&tim, NULL);
87
            break;
88
        case WRITING:
89
            WSS_session_jobs_dec(session);
90
            pthread_mutex_unlock(&session->lock);
91
            return;
92
        case IDLE:
93
            session->state = WRITING;
94
            WSS_write(server, session);
95
            WSS_session_jobs_dec(session);
96
            pthread_mutex_unlock(&session->lock);
97
            return;
98
        }
99
    } while (1);
100
}
101
102
void WSS_message_send(int fd, wss_opcode_t opcode, char *message, uint64_t message_length) {
103
    size_t k;
104
    size_t frames_count;
105
    wss_session_t *session;
106
    wss_frame_t **frames;
107
    wss_server_t *server = servers.http;
108
109
    if ( unlikely(NULL == (session = WSS_session_find(fd))) ) {
110
        WSS_log_error("Unable to find session to send message to");
111
        return;
112
    }
113
114
    WSS_session_jobs_inc(session);
115
116
    if (NULL != session->ssl && session->ssl_connected) {
117
        server = servers.https;
118
    }
119
120
    WSS_log_trace("Creating frames");
121
122
    frames_count = WSS_create_frames(server->config, opcode, message, message_length, &frames);
123
124
    WSS_message_send_frames(server, session, frames, frames_count);
125
126
    for (k = 0; likely(k < frames_count); k++) {
127
        WSS_free_frame(frames[k]);
128
    }
129
    WSS_free((void **) &frames);
130
}
131
132
void WSS_message_free(wss_message_t *msg) {
133
    if (NULL != msg) {
134
        if (NULL != msg->msg) {
135
            WSS_free((void **)&msg->msg);
136
        }
137
        WSS_free((void **)&msg);
138
    }
139
}