@@ -1793,14 +1793,14 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
17931793static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
17941794 va_list *ap) {
17951795 size_t len = c->send.len;
1796- mg_send(c, " \r\n", 10);
1796+ if (! mg_send(c, " \r\n", 10)) mg_error(c, "OOM" );
17971797 mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
17981798 if (c->send.len >= len + 10) {
17991799 mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10);
18001800 c->send.buf[len + 8] = '\r';
18011801 if (c->send.len == len + 10) c->is_resp = 0; // Last chunk, reset marker
18021802 }
1803- mg_send(c, "\r\n", 2);
1803+ if (! mg_send(c, "\r\n", 2)) mg_error(c, "OOM" );
18041804}
18051805
18061806void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
@@ -1812,8 +1812,7 @@ void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
18121812
18131813void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
18141814 mg_printf(c, "%lx\r\n", (unsigned long) len);
1815- mg_send(c, buf, len);
1816- mg_send(c, "\r\n", 2);
1815+ if (!mg_send(c, buf, len) || !mg_send(c, "\r\n", 2)) mg_error(c, "OOM");
18171816 if (len == 0) c->is_resp = 0;
18181817}
18191818
@@ -3353,8 +3352,8 @@ static const struct mg_mqtt_pmap s_prop_map[] = {
33533352 {MQTT_PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE, MQTT_PROP_TYPE_BYTE},
33543353 {MQTT_PROP_SHARED_SUBSCRIPTION_AVAILABLE, MQTT_PROP_TYPE_BYTE}};
33553354
3356- void mg_mqtt_send_header (struct mg_connection *c, uint8_t cmd, uint8_t flags ,
3357- uint32_t len) {
3355+ static bool mqtt_send_header (struct mg_connection *c, uint8_t cmd,
3356+ uint8_t flags, uint32_t len) {
33583357 uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
33593358 buf[0] = (uint8_t) ((cmd << 4) | flags);
33603359 do {
@@ -3363,15 +3362,20 @@ void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
33633362 if (len > 0) *vlen |= 0x80;
33643363 vlen++;
33653364 } while (len > 0 && vlen < &buf[sizeof(buf)]);
3366- mg_send(c, buf, (size_t) (vlen - buf));
3365+ return mg_send(c, buf, (size_t) (vlen - buf));
3366+ }
3367+
3368+ void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
3369+ uint32_t len) {
3370+ if (!mqtt_send_header(c, cmd, flags, len)) mg_error(c, "OOM");
33673371}
33683372
3369- static void mg_send_u16(struct mg_connection *c, uint16_t value) {
3370- mg_send(c, &value, sizeof(value));
3373+ static bool mg_send_u16(struct mg_connection *c, uint16_t value) {
3374+ return mg_send(c, &value, sizeof(value));
33713375}
33723376
3373- static void mg_send_u32(struct mg_connection *c, uint32_t value) {
3374- mg_send(c, &value, sizeof(value));
3377+ static bool mg_send_u32(struct mg_connection *c, uint32_t value) {
3378+ return mg_send(c, &value, sizeof(value));
33753379}
33763380
33773381static uint8_t varint_size(size_t length) {
@@ -3464,46 +3468,50 @@ static size_t get_props_size(struct mg_mqtt_prop *props, size_t count) {
34643468 return size;
34653469}
34663470
3467- static void mg_send_mqtt_properties(struct mg_connection *c,
3471+ static bool mg_send_mqtt_properties(struct mg_connection *c,
34683472 struct mg_mqtt_prop *props, size_t nprops) {
34693473 size_t total_size = get_properties_length(props, nprops);
34703474 uint8_t buf_v[4] = {0, 0, 0, 0};
34713475 uint8_t buf[4] = {0, 0, 0, 0};
34723476 size_t i, len = encode_varint(buf, total_size);
34733477
3474- mg_send(c, buf, (size_t) len);
3478+ if (! mg_send(c, buf, (size_t) len)) return false ;
34753479 for (i = 0; i < nprops; i++) {
3476- mg_send(c, &props[i].id, sizeof(props[i].id));
3480+ if (! mg_send(c, &props[i].id, sizeof(props[i].id))) return false ;
34773481 switch (mqtt_prop_type_by_id(props[i].id)) {
34783482 case MQTT_PROP_TYPE_STRING_PAIR:
3479- mg_send_u16(c, mg_htons((uint16_t) props[i].key.len));
3480- mg_send(c, props[i].key.buf, props[i].key.len);
3481- mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3482- mg_send(c, props[i].val.buf, props[i].val.len);
3483+ if (!mg_send_u16(c, mg_htons((uint16_t) props[i].key.len)) ||
3484+ !mg_send(c, props[i].key.buf, props[i].key.len) ||
3485+ !mg_send_u16(c, mg_htons((uint16_t) props[i].val.len)) ||
3486+ !mg_send(c, props[i].val.buf, props[i].val.len))
3487+ return false;
34833488 break;
34843489 case MQTT_PROP_TYPE_BYTE:
3485- mg_send(c, &props[i].iv, sizeof(uint8_t));
3490+ if (! mg_send(c, &props[i].iv, sizeof(uint8_t))) return false ;
34863491 break;
34873492 case MQTT_PROP_TYPE_SHORT:
3488- mg_send_u16(c, mg_htons((uint16_t) props[i].iv));
3493+ if (! mg_send_u16(c, mg_htons((uint16_t) props[i].iv))) return false ;
34893494 break;
34903495 case MQTT_PROP_TYPE_INT:
3491- mg_send_u32(c, mg_htonl((uint32_t) props[i].iv));
3496+ if (! mg_send_u32(c, mg_htonl((uint32_t) props[i].iv))) return false ;
34923497 break;
34933498 case MQTT_PROP_TYPE_STRING:
3494- mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3495- mg_send(c, props[i].val.buf, props[i].val.len);
3499+ if (!mg_send_u16(c, mg_htons((uint16_t) props[i].val.len)) ||
3500+ !mg_send(c, props[i].val.buf, props[i].val.len))
3501+ return false;
34963502 break;
34973503 case MQTT_PROP_TYPE_BINARY_DATA:
3498- mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3499- mg_send(c, props[i].val.buf, props[i].val.len);
3504+ if (!mg_send_u16(c, mg_htons((uint16_t) props[i].val.len)) ||
3505+ !mg_send(c, props[i].val.buf, props[i].val.len))
3506+ return false;
35003507 break;
35013508 case MQTT_PROP_TYPE_VARIABLE_INT:
35023509 len = encode_varint(buf_v, props[i].iv);
3503- mg_send(c, buf_v, (size_t) len);
3510+ if (! mg_send(c, buf_v, (size_t) len)) return false ;
35043511 break;
35053512 }
35063513 }
3514+ return true;
35073515}
35083516
35093517size_t mg_mqtt_next_prop(struct mg_mqtt_message *msg, struct mg_mqtt_prop *prop,
@@ -3596,33 +3604,41 @@ void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
35963604 total_len += get_props_size(opts->will_props, opts->num_will_props);
35973605 }
35983606
3599- mg_mqtt_send_header(c, MQTT_CMD_CONNECT, 0, (uint32_t) total_len);
3600- mg_send(c, hdr, sizeof(hdr));
36013607 // keepalive == 0 means "do not disconnect us!"
3602- mg_send_u16(c, mg_htons((uint16_t) opts->keepalive));
3608+ if (!mqtt_send_header(c, MQTT_CMD_CONNECT, 0, (uint32_t) total_len) ||
3609+ !mg_send(c, hdr, sizeof(hdr)) ||
3610+ !mg_send_u16(c, mg_htons((uint16_t) opts->keepalive)))
3611+ goto fail;
36033612
3604- if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3613+ if (c->is_mqtt5 && !mg_send_mqtt_properties(c, opts->props, opts->num_props))
3614+ goto fail;
36053615
3606- mg_send_u16(c, mg_htons((uint16_t) cid.len));
3607- mg_send(c, cid.buf, cid.len);
3616+ if (!mg_send_u16(c, mg_htons((uint16_t) cid.len)) ||
3617+ !mg_send(c, cid.buf, cid.len))
3618+ goto fail;
36083619
36093620 if (hdr[7] & MQTT_HAS_WILL) {
3610- if (c->is_mqtt5)
3611- mg_send_mqtt_properties(c, opts->will_props, opts->num_will_props);
3621+ if (c->is_mqtt5 &&
3622+ !mg_send_mqtt_properties(c, opts->will_props, opts->num_will_props))
3623+ goto fail;
36123624
3613- mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3614- mg_send(c, opts->topic.buf, opts->topic.len);
3615- mg_send_u16(c, mg_htons((uint16_t) opts->message.len));
3616- mg_send(c, opts->message.buf, opts->message.len);
3617- }
3618- if (opts->user.len > 0) {
3619- mg_send_u16(c, mg_htons((uint16_t) opts->user.len));
3620- mg_send(c, opts->user.buf, opts->user.len);
3621- }
3622- if (opts->pass.len > 0) {
3623- mg_send_u16(c, mg_htons((uint16_t) opts->pass.len));
3624- mg_send(c, opts->pass.buf, opts->pass.len);
3625+ if (!mg_send_u16(c, mg_htons((uint16_t) opts->topic.len)) ||
3626+ !mg_send(c, opts->topic.buf, opts->topic.len) ||
3627+ !mg_send_u16(c, mg_htons((uint16_t) opts->message.len)) ||
3628+ !mg_send(c, opts->message.buf, opts->message.len))
3629+ goto fail;
36253630 }
3631+ if (opts->user.len > 0 &&
3632+ (!mg_send_u16(c, mg_htons((uint16_t) opts->user.len)) ||
3633+ !mg_send(c, opts->user.buf, opts->user.len)))
3634+ goto fail;
3635+ if (opts->pass.len > 0 &&
3636+ (!mg_send_u16(c, mg_htons((uint16_t) opts->pass.len)) ||
3637+ !mg_send(c, opts->pass.buf, opts->pass.len)))
3638+ goto fail;
3639+ return;
3640+ fail:
3641+ mg_error(c, "OOM");
36263642}
36273643
36283644uint16_t mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
@@ -3637,20 +3653,28 @@ uint16_t mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
36373653 if (c->is_mqtt5) len += get_props_size(opts->props, opts->num_props);
36383654
36393655 if (opts->qos > 0 && id != 0) flags |= 1 << 3;
3640- mg_mqtt_send_header(c, MQTT_CMD_PUBLISH, flags, (uint32_t) len);
3641- mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3642- mg_send(c, opts->topic.buf, opts->topic.len);
3656+ if (!mqtt_send_header(c, MQTT_CMD_PUBLISH, flags, (uint32_t) len) ||
3657+ !mg_send_u16(c, mg_htons((uint16_t) opts->topic.len)) ||
3658+ !mg_send(c, opts->topic.buf, opts->topic.len))
3659+ goto fail;
36433660 if (opts->qos > 0) { // need to send 'id' field
36443661 if (id == 0) { // generate new one if not resending
36453662 if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
36463663 id = c->mgr->mqtt_id;
36473664 }
3648- mg_send_u16(c, mg_htons(id));
3665+ if (! mg_send_u16(c, mg_htons(id))) goto fail ;
36493666 }
36503667
3651- if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3668+ if (c->is_mqtt5 && !mg_send_mqtt_properties(c, opts->props, opts->num_props))
3669+ goto fail;
3670+
3671+ if (opts->message.len > 0 &&
3672+ !mg_send(c, opts->message.buf, opts->message.len))
3673+ goto fail;
3674+ return id;
36523675
3653- if (opts->message.len > 0) mg_send(c, opts->message.buf, opts->message.len);
3676+ fail:
3677+ mg_error(c, "OOM");
36543678 return id;
36553679}
36563680
@@ -3659,14 +3683,20 @@ void mg_mqtt_sub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
36593683 size_t plen = c->is_mqtt5 ? get_props_size(opts->props, opts->num_props) : 0;
36603684 size_t len = 2 + opts->topic.len + 2 + 1 + plen;
36613685
3662- mg_mqtt_send_header( c, MQTT_CMD_SUBSCRIBE, 2, (uint32_t) len);
3686+ if (!mqtt_send_header( c, MQTT_CMD_SUBSCRIBE, 2, (uint32_t) len)) goto fail ;
36633687 if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
3664- mg_send_u16(c, mg_htons(c->mgr->mqtt_id));
3665- if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3688+ if (!mg_send_u16(c, mg_htons(c->mgr->mqtt_id))) goto fail;
3689+
3690+ if (c->is_mqtt5 && !mg_send_mqtt_properties(c, opts->props, opts->num_props))
3691+ goto fail;
36663692
3667- mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3668- mg_send(c, opts->topic.buf, opts->topic.len);
3669- mg_send(c, &qos_, sizeof(qos_));
3693+ if (!mg_send_u16(c, mg_htons((uint16_t) opts->topic.len)) ||
3694+ !mg_send(c, opts->topic.buf, opts->topic.len) ||
3695+ !mg_send(c, &qos_, sizeof(qos_)))
3696+ goto fail;
3697+ return;
3698+ fail:
3699+ mg_error(c, "OOM");
36703700}
36713701
36723702int mg_mqtt_parse(const uint8_t *buf, size_t len, uint8_t version,
@@ -3773,15 +3803,16 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
37733803 uint32_t remaining_len = sizeof(id);
37743804 if (c->is_mqtt5) remaining_len += 2; // 3.4.2
37753805
3776- mg_mqtt_send_header(
3777- c,
3778- (uint8_t) (mm.qos == 2 ? MQTT_CMD_PUBREC : MQTT_CMD_PUBACK),
3779- 0, remaining_len);
3780- mg_send(c, &id, sizeof(id));
3806+ if (!mqtt_send_header(c,
3807+ (uint8_t) (mm.qos == 2 ? MQTT_CMD_PUBREC
3808+ : MQTT_CMD_PUBACK),
3809+ 0, remaining_len) ||
3810+ !mg_send(c, &id, sizeof(id)))
3811+ goto fail;
37813812
37823813 if (c->is_mqtt5) {
37833814 uint16_t zero = 0;
3784- mg_send(c, &zero, sizeof(zero));
3815+ if (! mg_send(c, &zero, sizeof(zero))) goto fail ;
37853816 }
37863817 }
37873818 mg_call(c, MG_EV_MQTT_MSG, &mm); // let the app handle qos stuff
@@ -3790,15 +3821,18 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
37903821 case MQTT_CMD_PUBREC: { // MQTT5: 3.5.2-1 TODO(): variable header rc
37913822 uint16_t id = mg_ntohs(mm.id);
37923823 uint32_t remaining_len = sizeof(id); // MQTT5 3.6.2-1
3793- mg_mqtt_send_header(c, MQTT_CMD_PUBREL, 2, remaining_len);
3794- mg_send(c, &id, sizeof(id)); // MQTT5 3.6.1-1, flags = 2
3824+ if (!mqtt_send_header(c, MQTT_CMD_PUBREL, 2,
3825+ remaining_len) // MQTT5 3.6.1-1, flags = 2
3826+ || !mg_send(c, &id, sizeof(id)))
3827+ goto fail;
37953828 break;
37963829 }
37973830 case MQTT_CMD_PUBREL: { // MQTT5: 3.6.2-1 TODO(): variable header rc
37983831 uint16_t id = mg_ntohs(mm.id);
37993832 uint32_t remaining_len = sizeof(id); // MQTT5 3.7.2-1
3800- mg_mqtt_send_header(c, MQTT_CMD_PUBCOMP, 0, remaining_len);
3801- mg_send(c, &id, sizeof(id));
3833+ if (!mqtt_send_header(c, MQTT_CMD_PUBCOMP, 0, remaining_len) ||
3834+ !mg_send(c, &id, sizeof(id)))
3835+ goto fail;
38023836 break;
38033837 }
38043838 }
@@ -3810,6 +3844,9 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
38103844 }
38113845 }
38123846 (void) ev_data;
3847+ return;
3848+ fail:
3849+ mg_error(c, "OOM");
38133850}
38143851
38153852void mg_mqtt_ping(struct mg_connection *nc) {
@@ -3824,19 +3861,24 @@ void mg_mqtt_disconnect(struct mg_connection *c,
38243861 const struct mg_mqtt_opts *opts) {
38253862 size_t len = 0;
38263863 if (c->is_mqtt5) len = 1 + get_props_size(opts->props, opts->num_props);
3827- mg_mqtt_send_header( c, MQTT_CMD_DISCONNECT, 0, (uint32_t) len);
3864+ if (!mqtt_send_header( c, MQTT_CMD_DISCONNECT, 0, (uint32_t) len)) goto fail ;
38283865
38293866 if (c->is_mqtt5) {
38303867 uint8_t zero = 0;
3831- mg_send(c, &zero, sizeof(zero)); // reason code
3832- mg_send_mqtt_properties(c, opts->props, opts->num_props);
3868+ if (!mg_send(c, &zero, sizeof(zero)) // reason code
3869+ || !mg_send_mqtt_properties(c, opts->props, opts->num_props))
3870+ goto fail;
38333871 }
3872+ return;
3873+ fail:
3874+ mg_error(c, "OOM");
38343875}
38353876
38363877struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
38373878 const struct mg_mqtt_opts *opts,
38383879 mg_event_handler_t fn, void *fn_data) {
3839- struct mg_connection *c = mg_connect_svc(mgr, url, fn, fn_data, mqtt_cb, NULL);
3880+ struct mg_connection *c =
3881+ mg_connect_svc(mgr, url, fn, fn_data, mqtt_cb, NULL);
38403882 if (c != NULL) {
38413883 struct mg_mqtt_opts empty;
38423884 memset(&empty, 0, sizeof(empty));
@@ -5537,6 +5579,7 @@ bool mg_open_listener(struct mg_connection *c, const char *url) {
55375579static void write_conn(struct mg_connection *c) {
55385580 long len = c->is_tls ? mg_tls_send(c, c->send.buf, c->send.len)
55395581 : mg_io_send(c, c->send.buf, c->send.len);
5582+ // TODO(): mg_tls_send() may return 0 forever on steady OOM
55405583 if (len == MG_IO_ERR) {
55415584 mg_error(c, "tx err");
55425585 } else if (len > 0) {
@@ -5615,7 +5658,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
56155658 res = tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf,
56165659 len);
56175660 } else {
5618- res = mg_iobuf_add(&c->send, c->send.len, buf, len);
5661+ res = (bool) mg_iobuf_add(&c->send, c->send.len, buf, len);
56195662 // res == 0 means an OOM condition (iobuf couldn't resize), yet this is so
56205663 // far recoverable, let the caller decide
56215664 }
@@ -8972,7 +9015,7 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
89729015 iolog(c, (char *) buf, n, false);
89739016 return n > 0;
89749017 } else {
8975- return mg_iobuf_add(&c->send, c->send.len, buf, len);
9018+ return (bool) mg_iobuf_add(&c->send, c->send.len, buf, len);
89769019 // returning 0 means an OOM condition (iobuf couldn't resize), yet this is
89779020 // so far recoverable, let the caller decide
89789021 }
@@ -9172,6 +9215,7 @@ static void write_conn(struct mg_connection *c) {
91729215 char *buf = (char *) c->send.buf;
91739216 size_t len = c->send.len;
91749217 long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_io_send(c, buf, len);
9218+ // TODO(): mg_tls_send() may return 0 forever on steady OOM
91759219 MG_DEBUG(("%lu %ld snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd,
91769220 (long) c->send.len, (long) c->send.size, (long) c->recv.len,
91779221 (long) c->recv.size, n, MG_SOCK_ERR(n)));
@@ -20349,7 +20393,7 @@ static void ws_handshake(struct mg_connection *c, const struct mg_str *wskey,
2034920393 mg_printf(c, "Sec-WebSocket-Protocol: %.*s\r\n", (int) wsproto->len,
2035020394 wsproto->buf);
2035120395 }
20352- mg_send(c, "\r\n", 2);
20396+ if (! mg_send(c, "\r\n", 2)) mg_error(c, "OOM" );
2035320397}
2035420398
2035520399static uint32_t be32(const uint8_t *p) {
0 commit comments