int mosquitto_reconnect(struct mosquitto *mosq) { int rc; if(!mosq) return MOSQ_ERR_INVAL; if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; rc = _mosquitto_socket_connect(mosq, mosq->host, mosq->port); if(rc){ return rc; } return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session); }
int mosquitto_reconnect(struct mosquitto *mosq) { int rc; struct _mosquitto_packet *packet; if(!mosq) return MOSQ_ERR_INVAL; if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; pthread_mutex_lock(&mosq->state_mutex); mosq->state = mosq_cs_new; pthread_mutex_unlock(&mosq->state_mutex); pthread_mutex_lock(&mosq->msgtime_mutex); mosq->last_msg_in = time(NULL); mosq->last_msg_out = time(NULL); pthread_mutex_unlock(&mosq->msgtime_mutex); mosq->ping_t = 0; _mosquitto_packet_cleanup(&mosq->in_packet); pthread_mutex_lock(&mosq->current_out_packet_mutex); pthread_mutex_lock(&mosq->out_packet_mutex); if(mosq->out_packet && !mosq->current_out_packet) { mosq->current_out_packet = mosq->out_packet; mosq->out_packet = mosq->out_packet->next; } while(mosq->current_out_packet) { packet = mosq->current_out_packet; /* Free data and reset values */ mosq->current_out_packet = mosq->out_packet; if(mosq->out_packet) { mosq->out_packet = mosq->out_packet->next; } _mosquitto_packet_cleanup(packet); _mosquitto_free(packet); } pthread_mutex_unlock(&mosq->out_packet_mutex); pthread_mutex_unlock(&mosq->current_out_packet_mutex); _mosquitto_messages_reconnect_reset(mosq); rc = _mosquitto_socket_connect(mosq, mosq->host, mosq->port); if(rc) { return rc; } return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session); }
int main(int argc, char *argv[]) { struct mosquitto *mosq; int fd; bool clean_session = true; int keepalive = 60; mosq = mosquitto_new("packetgen", NULL); if(!mosq){ fprintf(stderr, "Error: Out of memory.\n"); return 1; } /* CONNECT */ fd = open("mqtt.connect", O_CREAT|O_WRONLY, 00644); if(fd<0){ fprintf(stderr, "Error: Unable to open mqtt.connect for writing.\n"); return 1; } mosq->core.sock = fd; printf("_mosquitto_send_connect(): %d\n", _mosquitto_send_connect(mosq, keepalive, clean_session)); printf("loop: %d\n", mosquitto_loop_write(mosq)); close(fd); /* SUBSCRIBE */ fd = open("mqtt.subscribe", O_CREAT|O_WRONLY, 00644); if(fd<0){ fprintf(stderr, "Error: Unable to open mqtt.subscribe for writing.\n"); return 1; } mosq->core.sock = fd; printf("_mosquitto_send_subscribe(): %d\n", _mosquitto_send_subscribe(mosq, NULL, false, "subscribe/topic", 2)); printf("loop: %d\n", mosquitto_loop_write(mosq)); close(fd); mosquitto_destroy(mosq); return 0; }
static int _mosquitto_reconnect(struct mosquitto *mosq, bool blocking) { int rc; struct _mosquitto_packet *packet; if(!mosq) return MOSQ_ERR_INVAL; if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; pthread_mutex_lock(&mosq->state_mutex); #ifdef WITH_SOCKS if(mosq->socks5_host){ mosq->state = mosq_cs_socks5_new; }else #endif { mosq->state = mosq_cs_new; } pthread_mutex_unlock(&mosq->state_mutex); pthread_mutex_lock(&mosq->msgtime_mutex); mosq->last_msg_in = mosquitto_time(); mosq->last_msg_out = mosquitto_time(); pthread_mutex_unlock(&mosq->msgtime_mutex); mosq->ping_t = 0; _mosquitto_packet_cleanup(&mosq->in_packet); pthread_mutex_lock(&mosq->current_out_packet_mutex); pthread_mutex_lock(&mosq->out_packet_mutex); if(mosq->out_packet && !mosq->current_out_packet){ mosq->current_out_packet = mosq->out_packet; mosq->out_packet = mosq->out_packet->next; } while(mosq->current_out_packet){ packet = mosq->current_out_packet; /* Free data and reset values */ mosq->current_out_packet = mosq->out_packet; if(mosq->out_packet){ mosq->out_packet = mosq->out_packet->next; } _mosquitto_packet_cleanup(packet); _mosquitto_free(packet); } pthread_mutex_unlock(&mosq->out_packet_mutex); pthread_mutex_unlock(&mosq->current_out_packet_mutex); _mosquitto_messages_reconnect_reset(mosq); #ifdef WITH_SOCKS if(mosq->socks5_host){ rc = _mosquitto_socket_connect(mosq, mosq->socks5_host, mosq->socks5_port, mosq->bind_address, blocking); }else #endif { rc = _mosquitto_socket_connect(mosq, mosq->host, mosq->port, mosq->bind_address, blocking); } if(rc>0){ return rc; } #ifdef WITH_SOCKS if(mosq->socks5_host){ return mosquitto__socks5_send(mosq); }else #endif { return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session); } }
int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) { int rc; int i; char *notification_topic; int notification_topic_len; uint8_t notification_payload; if(!context || !context->bridge) return MOSQ_ERR_INVAL; context->state = mosq_cs_new; context->sock = INVALID_SOCKET; context->last_msg_in = mosquitto_time(); context->next_msg_out = mosquitto_time() + context->bridge->keepalive; context->keepalive = context->bridge->keepalive; context->clean_session = context->bridge->clean_session; context->in_packet.payload = NULL; context->ping_t = 0; context->bridge->lazy_reconnect = false; mqtt3_bridge_packet_cleanup(context); mqtt3_db_message_reconnect_reset(db, context); if(context->clean_session){ mqtt3_db_messages_delete(db, context); } /* Delete all local subscriptions even for clean_session==false. We don't * remove any messages and the next loop carries out the resubscription * anyway. This means any unwanted subs will be removed. */ mqtt3_subs_clean_session(db, context); for(i=0; i<context->bridge->topic_count; i++){ if(context->bridge->topics[i].direction == bd_out || context->bridge->topics[i].direction == bd_both){ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Bridge %s doing local SUBSCRIBE on topic %s", context->id, context->bridge->topics[i].local_topic); if(mqtt3_sub_add(db, context, context->bridge->topics[i].local_topic, context->bridge->topics[i].qos, &db->subs)) return 1; } } if(context->bridge->notifications){ if(context->bridge->notification_topic){ if(!context->bridge->initial_notification_done){ notification_payload = '0'; mqtt3_db_messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1); context->bridge->initial_notification_done = true; } notification_payload = '0'; rc = _mosquitto_will_set(context, context->bridge->notification_topic, 1, ¬ification_payload, 1, true); if(rc != MOSQ_ERR_SUCCESS){ return rc; } }else{ notification_topic_len = strlen(context->bridge->remote_clientid)+strlen("$SYS/broker/connection//state"); notification_topic = _mosquitto_malloc(sizeof(char)*(notification_topic_len+1)); if(!notification_topic) return MOSQ_ERR_NOMEM; snprintf(notification_topic, notification_topic_len+1, "$SYS/broker/connection/%s/state", context->bridge->remote_clientid); if(!context->bridge->initial_notification_done){ notification_payload = '0'; mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1); context->bridge->initial_notification_done = true; } notification_payload = '0'; rc = _mosquitto_will_set(context, notification_topic, 1, ¬ification_payload, 1, true); _mosquitto_free(notification_topic); if(rc != MOSQ_ERR_SUCCESS){ return rc; } } } _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, false); if(rc > 0 ){ if(rc == MOSQ_ERR_TLS){ _mosquitto_socket_close(db, context); return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } return rc; } HASH_ADD(hh_sock, db->contexts_by_sock, sock, sizeof(context->sock), context); if(rc == MOSQ_ERR_CONN_PENDING){ context->state = mosq_cs_connect_pending; } rc = _mosquitto_send_connect(context, context->keepalive, context->clean_session); if(rc == MOSQ_ERR_SUCCESS){ return MOSQ_ERR_SUCCESS; }else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){ return MOSQ_ERR_SUCCESS; }else{ if(rc == MOSQ_ERR_TLS){ return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } _mosquitto_socket_close(db, context); 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; }
int mqtt3_bridge_connect(struct mosquitto_db *db, struct mosquitto *context) { int rc; int i; char *notification_topic; int notification_topic_len; uint8_t notification_payload; if(!context || !context->bridge) return MOSQ_ERR_INVAL; context->state = mosq_cs_new; context->sock = -1; context->last_msg_in = mosquitto_time(); context->last_msg_out = mosquitto_time(); context->keepalive = context->bridge->keepalive; context->clean_session = context->bridge->clean_session; context->in_packet.payload = NULL; context->ping_t = 0; context->bridge->lazy_reconnect = false; mqtt3_bridge_packet_cleanup(context); mqtt3_db_message_reconnect_reset(context); if(context->clean_session){ mqtt3_db_messages_delete(context); } rc = mosquitto_unpwd_check(db, context->bridge->local_username, context->bridge->local_password); switch(rc){ case MOSQ_ERR_SUCCESS: break; case MOSQ_ERR_AUTH: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Bridge %s failed authentication on local broker.", context->id); return rc; case MOSQ_ERR_UNKNOWN: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Bridge %s returned application error in authorisation.", context->id); return rc; default: _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Unknown error in authentication for bridge %s.", context->id); return rc; } /* Delete all local subscriptions even for clean_session==false. We don't * remove any messages and the next loop carries out the resubscription * anyway. This means any unwanted subs will be removed. */ mqtt3_subs_clean_session(db, context, &db->subs); for(i=0; i<context->bridge->topic_count; i++){ if(context->bridge->topics[i].direction == bd_out || context->bridge->topics[i].direction == bd_both){ _mosquitto_log_printf(NULL, MOSQ_LOG_DEBUG, "Bridge %s doing local SUBSCRIBE on topic %s", context->id, context->bridge->topics[i].local_topic); if(mqtt3_sub_add(db, context, context->bridge->topics[i].local_topic, context->bridge->topics[i].qos, &db->subs)) return 1; } } if(context->bridge->notifications){ notification_payload = '0'; if(context->bridge->notification_topic){ mqtt3_db_messages_easy_queue(db, context, context->bridge->notification_topic, 1, 1, ¬ification_payload, 1); rc = _mosquitto_will_set(context, context->bridge->notification_topic, 1, ¬ification_payload, 1, true); if(rc != MOSQ_ERR_SUCCESS){ return rc; } }else{ notification_topic_len = strlen(context->id)+strlen("$SYS/broker/connection//state"); notification_topic = _mosquitto_malloc(sizeof(char)*(notification_topic_len+1)); if(!notification_topic) return MOSQ_ERR_NOMEM; snprintf(notification_topic, notification_topic_len+1, "$SYS/broker/connection/%s/state", context->id); mqtt3_db_messages_easy_queue(db, context, notification_topic, 1, 1, ¬ification_payload, 1); rc = _mosquitto_will_set(context, notification_topic, 1, ¬ification_payload, 1, true); if(rc != MOSQ_ERR_SUCCESS){ _mosquitto_free(notification_topic); return rc; } _mosquitto_free(notification_topic); } } _mosquitto_log_printf(NULL, MOSQ_LOG_NOTICE, "Connecting bridge %s (%s:%d)", context->bridge->name, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port); rc = _mosquitto_socket_connect(context, context->bridge->addresses[context->bridge->cur_address].address, context->bridge->addresses[context->bridge->cur_address].port, NULL, true); if(rc != MOSQ_ERR_SUCCESS){ if(rc == MOSQ_ERR_TLS){ return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } return rc; } rc = _mosquitto_send_connect(context, context->keepalive, context->clean_session); if(rc == MOSQ_ERR_SUCCESS){ return MOSQ_ERR_SUCCESS; }else if(rc == MOSQ_ERR_ERRNO && errno == ENOTCONN){ return MOSQ_ERR_SUCCESS; }else{ if(rc == MOSQ_ERR_TLS){ return rc; /* Error already printed */ }else if(rc == MOSQ_ERR_ERRNO){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", strerror(errno)); }else if(rc == MOSQ_ERR_EAI){ _mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error creating bridge: %s.", gai_strerror(errno)); } _mosquitto_socket_close(context); return rc; } }
int mosquitto_reconnect(struct mosquitto *mosq) { int rc; struct _mosquitto_packet *packet; //输入参数是否正规的判断 if(!mosq) return MOSQ_ERR_INVAL; if(!mosq->host || mosq->port <= 0) return MOSQ_ERR_INVAL; //更新连接状态 pthread_mutex_lock(&mosq->state_mutex); mosq->state = mosq_cs_new; pthread_mutex_unlock(&mosq->state_mutex); //重置最后接受和发送信息的时间 pthread_mutex_lock(&mosq->msgtime_mutex); mosq->last_msg_in = time(NULL); mosq->last_msg_out = time(NULL); pthread_mutex_unlock(&mosq->msgtime_mutex); //PING命令等待时间置0 mosq->ping_t = 0; //清理接受包的信息 _mosquitto_packet_cleanup(&mosq->in_packet); pthread_mutex_lock(&mosq->current_out_packet_mutex); pthread_mutex_lock(&mosq->out_packet_mutex); //当发送包信息已经初始化 并且 当前发送包信息为空 if(mosq->out_packet && !mosq->current_out_packet) { mosq->current_out_packet = mosq->out_packet; mosq->out_packet = mosq->out_packet->next; } //清理发送包信息 while(mosq->current_out_packet) { //指向当前发送包信息 packet = mosq->current_out_packet; /* Free data and reset values */ mosq->current_out_packet = mosq->out_packet; if(mosq->out_packet) { mosq->out_packet = mosq->out_packet->next; } //清理包信息 _mosquitto_packet_cleanup(packet); //释放包 _mosquitto_free(packet); } pthread_mutex_unlock(&mosq->out_packet_mutex); pthread_mutex_unlock(&mosq->current_out_packet_mutex); //删除收到的信息内容,并删除不需要等待回应的发出的信息内容 _mosquitto_messages_reconnect_reset(mosq); //创建一个socket,连接到指定的host和port rc = _mosquitto_socket_connect(mosq, mosq->host, mosq->port); if(rc) { return rc; } return _mosquitto_send_connect(mosq, mosq->keepalive, mosq->clean_session); }