int mosquitto_loop_read(struct mosquitto *mosq, int max_packets) { int rc; int i; if(max_packets < 1) return MOSQ_ERR_INVAL; pthread_mutex_lock(&mosq->out_message_mutex); max_packets = mosq->out_queue_len; pthread_mutex_unlock(&mosq->out_message_mutex); pthread_mutex_lock(&mosq->in_message_mutex); max_packets += mosq->in_queue_len; pthread_mutex_unlock(&mosq->in_message_mutex); if(max_packets < 1) max_packets = 1; /* Queue len here tells us how many messages are awaiting processing and * have QoS > 0. We should try to deal with that many in this loop in order * to keep up. */ for(i=0; i<max_packets; i++){ #ifdef WITH_SOCKS if(mosq->socks5_host){ rc = mosquitto__socks5_read(mosq); }else #endif { rc = _mosquitto_packet_read(mosq); } if(rc || errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return _mosquitto_loop_rc_handle(mosq, rc); } } return rc; }
static void loop_handle_reads_writes(struct mosquitto_db *db, struct pollfd *pollfds) { int i; for(i=0; i<db->context_count; i++){ if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ assert(pollfds[db->contexts[i]->pollfd_index].fd == db->contexts[i]->sock); #ifdef WITH_TLS if(pollfds[db->contexts[i]->pollfd_index].revents & POLLOUT || db->contexts[i]->want_write || (db->contexts[i]->ssl && db->contexts[i]->state == mosq_cs_new)){ #else if(pollfds[db->contexts[i]->pollfd_index].revents & POLLOUT){ #endif if(_mosquitto_packet_write(db->contexts[i])){ if(db->config->connection_messages == true){ if(db->contexts[i]->state != mosq_cs_disconnecting){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Socket write error on client %s, disconnecting.", db->contexts[i]->id); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", db->contexts[i]->id); } } /* Write error or other that means we should disconnect */ mqtt3_context_disconnect(db, db->contexts[i]); } } } if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ assert(pollfds[db->contexts[i]->pollfd_index].fd == db->contexts[i]->sock); #ifdef WITH_TLS if(pollfds[db->contexts[i]->pollfd_index].revents & POLLIN || db->contexts[i]->want_read || (db->contexts[i]->ssl && db->contexts[i]->state == mosq_cs_new)){ #else if(pollfds[db->contexts[i]->pollfd_index].revents & POLLIN){ #endif if(_mosquitto_packet_read(db, db->contexts[i])){ if(db->config->connection_messages == true){ if(db->contexts[i]->state != mosq_cs_disconnecting){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Socket read error on client %s, disconnecting.", db->contexts[i]->id); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", db->contexts[i]->id); } } /* Read error or other that means we should disconnect */ mqtt3_context_disconnect(db, db->contexts[i]); } } } if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ if(pollfds[db->contexts[i]->pollfd_index].revents & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL)){ do_disconnect(db, i); } } } }
int mosquitto_loop_read(struct mosquitto *mosq, int max_packets) { int rc; int i; if(max_packets < 1) return MOSQ_ERR_INVAL; max_packets = mosq->queue_len; if(max_packets < 1) max_packets = 1; /* Queue len here tells us how many messages are awaiting processing and * have QoS > 0. We should try to deal with that many in this loop in order * to keep up. */ for(i=0; i<max_packets; i++) { rc = _mosquitto_packet_read(mosq); if(rc || errno == EAGAIN || errno == COMPAT_EWOULDBLOCK) { return _mosquitto_loop_rc_handle(mosq, rc); } } return rc; }
int mosquitto__socks5_read(struct mosquitto *mosq) { ssize_t len; uint8_t *payload; uint8_t i; if(mosq->state == mosq_cs_socks5_start){ while(mosq->in_packet.to_process > 0){ len = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); if(len > 0){ mosq->in_packet.pos += len; mosq->in_packet.to_process -= len; }else{ #ifdef WIN32 errno = WSAGetLastError(); #endif if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return MOSQ_ERR_SUCCESS; }else{ _mosquitto_packet_cleanup(&mosq->in_packet); switch(errno){ case 0: return MOSQ_ERR_PROXY; case COMPAT_ECONNRESET: return MOSQ_ERR_CONN_LOST; default: return MOSQ_ERR_ERRNO; } } } } if(mosq->in_packet.payload[0] != 5){ _mosquitto_packet_cleanup(&mosq->in_packet); return MOSQ_ERR_PROXY; } switch(mosq->in_packet.payload[1]){ case SOCKS_AUTH_NONE: _mosquitto_packet_cleanup(&mosq->in_packet); mosq->state = mosq_cs_socks5_auth_ok; return mosquitto__socks5_send(mosq); case SOCKS_AUTH_USERPASS: _mosquitto_packet_cleanup(&mosq->in_packet); mosq->state = mosq_cs_socks5_send_userpass; return mosquitto__socks5_send(mosq); default: _mosquitto_packet_cleanup(&mosq->in_packet); return MOSQ_ERR_AUTH; } }else if(mosq->state == mosq_cs_socks5_userpass_reply){ while(mosq->in_packet.to_process > 0){ len = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); if(len > 0){ mosq->in_packet.pos += len; mosq->in_packet.to_process -= len; }else{ #ifdef WIN32 errno = WSAGetLastError(); #endif if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return MOSQ_ERR_SUCCESS; }else{ _mosquitto_packet_cleanup(&mosq->in_packet); switch(errno){ case 0: return MOSQ_ERR_PROXY; case COMPAT_ECONNRESET: return MOSQ_ERR_CONN_LOST; default: return MOSQ_ERR_ERRNO; } } } } if(mosq->in_packet.payload[0] != 1){ _mosquitto_packet_cleanup(&mosq->in_packet); return MOSQ_ERR_PROXY; } if(mosq->in_packet.payload[1] == 0){ _mosquitto_packet_cleanup(&mosq->in_packet); mosq->state = mosq_cs_socks5_auth_ok; return mosquitto__socks5_send(mosq); }else{ i = mosq->in_packet.payload[1]; _mosquitto_packet_cleanup(&mosq->in_packet); switch(i){ case SOCKS_REPLY_CONNECTION_NOT_ALLOWED: return MOSQ_ERR_AUTH; case SOCKS_REPLY_NETWORK_UNREACHABLE: case SOCKS_REPLY_HOST_UNREACHABLE: case SOCKS_REPLY_CONNECTION_REFUSED: return MOSQ_ERR_NO_CONN; case SOCKS_REPLY_GENERAL_FAILURE: case SOCKS_REPLY_TTL_EXPIRED: case SOCKS_REPLY_COMMAND_NOT_SUPPORTED: case SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: return MOSQ_ERR_PROXY; default: return MOSQ_ERR_INVAL; } return MOSQ_ERR_PROXY; } }else if(mosq->state == mosq_cs_socks5_request){ while(mosq->in_packet.to_process > 0){ len = _mosquitto_net_read(mosq, &(mosq->in_packet.payload[mosq->in_packet.pos]), mosq->in_packet.to_process); if(len > 0){ mosq->in_packet.pos += len; mosq->in_packet.to_process -= len; }else{ #ifdef WIN32 errno = WSAGetLastError(); #endif if(errno == EAGAIN || errno == COMPAT_EWOULDBLOCK){ return MOSQ_ERR_SUCCESS; }else{ _mosquitto_packet_cleanup(&mosq->in_packet); switch(errno){ case 0: return MOSQ_ERR_PROXY; case COMPAT_ECONNRESET: return MOSQ_ERR_CONN_LOST; default: return MOSQ_ERR_ERRNO; } } } } if(mosq->in_packet.packet_length == 5){ /* First part of the packet has been received, we now know what else to expect. */ if(mosq->in_packet.payload[3] == SOCKS_ATYPE_IP_V4){ mosq->in_packet.to_process += 4+2-1; /* 4 bytes IPv4, 2 bytes port, -1 byte because we've already read the first byte */ mosq->in_packet.packet_length += 4+2-1; }else if(mosq->in_packet.payload[3] == SOCKS_ATYPE_IP_V6){ mosq->in_packet.to_process += 16+2-1; /* 16 bytes IPv6, 2 bytes port, -1 byte because we've already read the first byte */ mosq->in_packet.packet_length += 16+2-1; }else if(mosq->in_packet.payload[3] == SOCKS_ATYPE_DOMAINNAME){ if(mosq->in_packet.payload[4] > 0 && mosq->in_packet.payload[4] <= 255){ mosq->in_packet.to_process += mosq->in_packet.payload[4]; mosq->in_packet.packet_length += mosq->in_packet.payload[4]; } }else{ _mosquitto_packet_cleanup(&mosq->in_packet); return MOSQ_ERR_PROTOCOL; } payload = _mosquitto_realloc(mosq->in_packet.payload, mosq->in_packet.packet_length); if(payload){ mosq->in_packet.payload = payload; }else{ _mosquitto_packet_cleanup(&mosq->in_packet); return MOSQ_ERR_NOMEM; } payload = _mosquitto_realloc(mosq->in_packet.payload, mosq->in_packet.packet_length); if(payload){ mosq->in_packet.payload = payload; }else{ _mosquitto_packet_cleanup(&mosq->in_packet); return MOSQ_ERR_NOMEM; } return MOSQ_ERR_SUCCESS; } /* Entire packet is now read. */ if(mosq->in_packet.payload[0] != 5){ _mosquitto_packet_cleanup(&mosq->in_packet); return MOSQ_ERR_PROXY; } if(mosq->in_packet.payload[1] == 0){ /* Auth passed */ _mosquitto_packet_cleanup(&mosq->in_packet); mosq->state = mosq_cs_new; return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session); }else{ i = mosq->in_packet.payload[1]; _mosquitto_packet_cleanup(&mosq->in_packet); mosq->state = mosq_cs_socks5_new; switch(i){ case SOCKS_REPLY_CONNECTION_NOT_ALLOWED: return MOSQ_ERR_AUTH; case SOCKS_REPLY_NETWORK_UNREACHABLE: case SOCKS_REPLY_HOST_UNREACHABLE: case SOCKS_REPLY_CONNECTION_REFUSED: return MOSQ_ERR_NO_CONN; case SOCKS_REPLY_GENERAL_FAILURE: case SOCKS_REPLY_TTL_EXPIRED: case SOCKS_REPLY_COMMAND_NOT_SUPPORTED: case SOCKS_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: return MOSQ_ERR_PROXY; default: return MOSQ_ERR_INVAL; } } }else{ return _mosquitto_packet_read(mosq); } return MOSQ_ERR_SUCCESS; }
static void loop_handle_reads_writes(struct mosquitto_db *db, struct epoll_event *events, int efd) { int i, s; for (i = 0; i < db->context_count; i++) { if (db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ /* if (events[db->contexts[i]->pollfd_index].data.fd != db->contexts[i]->sock) { */ /* printf ("%d---%d\n", events[db->contexts[i]->pollfd_index].data.fd, db->contexts[i]->sock); */ /* printf ("%d\n", i); */ /* int n; */ /* for (n = 0; n < sizeof (db->contexts); ++n) */ /* { */ /* printf ("%d----%d\n", db->contexts[n]->pollfd_index, events[db->contexts[i]->pollfd_index].data.fd); */ /* } */ /* } */ /* assert(events[db->contexts[i]->pollfd_index].data.fd == db->contexts[i]->sock); */ #ifdef WITH_TLS if (events[db->contexts[i]->pollfd_index].events & EPOLLOUT || db->contexts[i]->want_write || (db->contexts[i]->ssl && db->contexts[i]->state == mosq_cs_new)) { #else if(events[db->contexts[i]->epollfd_index].events & EPOLLOUT){ #endif if(_mosquitto_packet_write(db->contexts[i])){ if(db->config->connection_messages == true){ if(db->contexts[i]->state != mosq_cs_disconnecting){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Socket write error on client %s, disconnecting.", db->contexts[i]->id); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", db->contexts[i]->id); } } /* Write error or other that means we should disconnect */ mqtt3_context_disconnect(db, db->contexts[i]); } } } if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ /* assert(events[db->contexts[i]->pollfd_index].data.fd == db->contexts[i]->sock); */ #ifdef WITH_TLS if(events[db->contexts[i]->pollfd_index].events & EPOLLIN || db->contexts[i]->want_read || (db->contexts[i]->ssl && db->contexts[i]->state == mosq_cs_new)){ #else if(events[db->contexts[i]->pollfd_index].events & EPOLLIN){ #endif if(_mosquitto_packet_read(db, db->contexts[i])){ if(db->config->connection_messages == true){ if(db->contexts[i]->state != mosq_cs_disconnecting){ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Socket read error on client %s, disconnecting.", db->contexts[i]->id); }else{ _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Client %s disconnected.", db->contexts[i]->id); } } /* Read error or other that means we should disconnect */ mqtt3_context_disconnect(db, db->contexts[i]); } } } if(db->contexts[i] && db->contexts[i]->sock != INVALID_SOCKET){ if(events[db->contexts[i]->pollfd_index].events & (EPOLLHUP | POLLRDHUP | EPOLLERR)){ s = epoll_ctl (efd, EPOLL_CTL_DEL, events[db->contexts[i]->pollfd_index].data.fd, &events[db->contexts[i]->pollfd_index]); do_disconnect(db, i); } } } }
int mosquitto_loop_read(struct mosquitto *mosq) { return _mosquitto_packet_read(mosq); }