129 #include "../../interfaces/ARDUINO/TCPHelper_ARDUINO.h"
131 #include "../../interfaces/LINUX/TCPHelper_POSIX.h"
135 #define Serial DummyPrint
137 static void print(
const char *s)
141 static void print(
int n)
145 static void println(
const char *s)
149 static void println(
int n)
163 #define PJON_FAIL 0x100
166 #ifndef ETCP_MAX_REMOTE_NODES
167 #define ETCP_MAX_REMOTE_NODES 10
170 #define ETCP_DEFAULT_PORT 7000
175 #ifndef ETCP_MAX_PACKET_SIZE
176 #define ETCP_MAX_PACKET_SIZE 300
185 #ifndef ETCP_IDLE_TIMEOUT
186 #define ETCP_IDLE_TIMEOUT 30000ul
190 #define ETCP_HEADER 0x18ABC427ul
191 #define ETCP_FOOTER 0x9ABE8873ul
192 #define ETCP_SINGLE_SOCKET_HEADER 0x4E92AC90ul
193 #define ETCP_SINGLE_SOCKET_FOOTER 0x7BB1E3F4ul
194 #define ETCP_CONNECTION_HEADER_A 0xFEDFED67ul // Primary socket, packets in initiated direction
195 #define ETCP_CONNECTION_HEADER_A_ACK 0xFEDFED68ul // Same, but request ACK for all packets
196 #define ETCP_CONNECTION_HEADER_B 0xFEDFED77ul // Reverse socket, packets in reverse direction
201 #if defined(ARDUINO) && !defined(UIPETHERNET_H)
202 #define ETCP_ERROR_READ 0
204 #define ETCP_ERROR_READ -1
207 typedef void (*link_receiver)(
209 const uint8_t *payload,
211 void *callback_object
214 typedef void (*link_error)(
227 buf =
new uint8_t[size];
235 uint8_t* operator()()
259 int16_t _current_device = -1;
262 bool _ack_requested =
false;
265 uint32_t _connection_time = 0;
266 uint32_t _connection_count = 0;
267 uint32_t _last_receive_time = 0;
271 link_receiver _receiver = NULL;
272 link_error _error = NULL;
273 void *_callback_object = NULL;
276 uint8_t _local_id = 0;
277 uint8_t _local_ip[4];
278 uint16_t _local_port = ETCP_DEFAULT_PORT;
281 uint8_t _remote_node_count = 0;
282 uint8_t _remote_id[ETCP_MAX_REMOTE_NODES];
283 uint8_t _remote_ip[ETCP_MAX_REMOTE_NODES][4];
284 uint16_t _remote_port[ETCP_MAX_REMOTE_NODES];
287 bool _keep_connection =
false;
290 bool _single_socket =
false;
293 bool _request_ack =
false;
298 bool _receive_and_discard =
false;
307 bool _initiate_both_sockets_in_same_direction =
false;
309 bool _initiator =
true;
315 memset(_local_ip, 0, 4);
319 int16_t find_remote_node(uint8_t
id)
321 for(uint8_t i = 0; i < _remote_node_count; i++)
322 if(_remote_id[i] ==
id) {
333 uint16_t timeout_ms = 2000
336 int32_t total_bytes_read = 0, bytes_read = ETCP_ERROR_READ;
337 uint32_t start_ms = PJON_MILLIS();
343 #ifdef HAS_ETHERNETUDP // Avoid using blocking read until there is data present
346 client.connected() &&
347 (avail = client.available()) <= 0 &&
348 (uint32_t)(PJON_MILLIS() - start_ms) <
min(1000, timeout_ms)
350 PJON_DELAY_MICROSECONDS(250);
357 bytes_read = client.read(
358 &contents[total_bytes_read],
359 length - total_bytes_read
363 total_bytes_read += bytes_read;
366 bytes_read != ETCP_ERROR_READ &&
367 total_bytes_read < length &&
368 (uint32_t)(PJON_MILLIS() - start_ms) < timeout_ms
371 if(bytes_read == ETCP_ERROR_READ) {
373 #ifdef ETCP_ERROR_PRINT
374 Serial.println(F(
"Read failed, closing cl"));
377 return total_bytes_read;
384 uint16_t return_value = PJON_FAIL;
385 uint32_t start_ms = PJON_MILLIS(), avail;
388 client.connected() &&
389 (avail = client.available()) <= 0 &&
390 (uint32_t)(PJON_MILLIS() - start_ms) < 1000
392 PJON_DELAY_MICROSECONDS(250);
395 avail = client.connected() ? client.available() : 0;
399 #ifdef ETCP_DEBUG_PRINT
400 Serial.println(F(
"Recv from cl"));
404 bool ok = read_until_header(client, ETCP_HEADER);
405 #ifdef ETCP_DEBUG_PRINT
406 Serial.print(F(
"Read header, stat "));
411 int16_t bytes_read = 0;
412 uint8_t sender_id = 0;
413 uint32_t content_length = 0;
416 bytes_read = read_bytes(client, buf, 5);
417 if(bytes_read != 5) {
420 memcpy(&sender_id, buf, 1);
421 memcpy(&content_length, &buf[1], 4);
422 content_length = ntohl(content_length);
423 if(content_length == 0) {
430 if (content_length > ETCP_MAX_PACKET_SIZE) {
437 bytes_read = read_bytes(client, (uint8_t*)buf(), content_length);
438 if((uint32_t)bytes_read != content_length) {
446 bytes_read = read_bytes(client, (uint8_t*) &foot, 4);
447 if(bytes_read != 4 || foot != htonl(ETCP_FOOTER)) {
452 #ifdef ETCP_DEBUG_PRINT
453 Serial.print(F(
"Stat rec: "));
455 Serial.print(
" len: ");
456 Serial.println(content_length);
458 #if defined(ETCP_ERROR_PRINT)
460 Serial.print(F(
"FAIL rec: "));
461 Serial.println(bytes_read);
466 return_value = ok ? PJON_ACK : PJON_FAIL;
468 _last_receive_time = PJON_MILLIS();
470 if (_ack_requested && !_receive_and_discard) {
474 uint16_t r = htons(return_value);
475 acklen = client.write((uint8_t*) &r, 2);
479 #ifdef ETCP_DEBUG_PRINT
480 Serial.print(
"Sent ");
481 Serial.print(ok ?
"PJON_ACK: " :
"PJON_FAIL: ");
482 Serial.println(acklen);
485 #if defined(ETCP_ERROR_PRINT)
487 Serial.println(
"FAILURE sending ACK");
494 if(ok && !_receive_and_discard && content_length > 0) {
495 _receiver(sender_id, (uint8_t*)buf(), content_length, _callback_object);
506 bool connect(uint8_t
id)
509 int16_t pos = find_remote_node(
id);
512 bool disconnect = !_keep_connection,
513 reverse = _initiate_both_sockets_in_same_direction && _initiator;
516 if(!disconnect && _client_out && _current_device !=
id) {
518 #ifdef ETCP_DEBUG_PRINT
519 Serial.println(F(
"Switch conn to another srv"));
522 _current_device = -1;
526 if (!disconnect && _client_out && !_client_out.connected()) {
529 #ifdef ETCP_SINGLE_DIRECTION
530 if (!disconnect && reverse && _client_in && !_client_in.connected()) {
533 if (!disconnect && reverse && (!_client_in || !_client_out)) {
536 if (!disconnect && reverse && _client_in && got_receive_timeout()) {
537 #ifdef ETCP_ERROR_PRINT
538 Serial.println(F(
"Receive timeout, disconn."));
548 bool connected = _client_out;
549 #ifdef ETCP_DEBUG_PRINT
551 Serial.print(F(
"Conn to srv pos="));
561 bool did_connect =
false;
563 #ifdef ETCP_DEBUG_PRINT
564 Serial.println(
"Conn..");
566 #ifdef HAS_ETHERNETUDP // Arduino, otherwise POSIX
567 connected = _client_out.connect(_remote_ip[pos], _remote_port[pos]);
570 if (_client_out.prepare_connect(_remote_ip[pos], _remote_port[pos])) {
572 uint32_t start = PJON_MILLIS();
574 if (!_initiate_both_sockets_in_same_direction && !_single_socket && _server) {
580 status = _client_out.try_connect();
582 PJON_DELAY_MICROSECONDS(PJON_RANDOM(250));
584 }
while (status == 0 && (uint32_t)(PJON_MILLIS()-start)<4000);
585 connected = (status == 1);
589 #ifdef ETCP_DEBUG_PRINT
590 Serial.println(connected ?
"Conn to srv" :
"Failed conn to srv");
594 uint32_t conn_header = htonl(_request_ack ? ETCP_CONNECTION_HEADER_A_ACK :
595 ETCP_CONNECTION_HEADER_A);
596 if (_client_out.write((uint8_t*) &conn_header, 4) != 4) {
598 #ifdef ETCP_ERROR_PRINT
599 Serial.println(F(
"Disconn. failed write connhead"));
610 bool connected_rev =
false;
611 #ifdef ETCP_SINGLE_DIRECTION
612 if (connected && reverse) {
613 connected_rev = _client_in;
614 if (!connected_rev) {
615 #ifdef ETCP_DEBUG_PRINT
616 Serial.println(
"Conn rev..");
618 uint32_t start = PJON_MILLIS();
620 connected_rev = _client_in.connect(_remote_ip[pos], _remote_port[pos]);
621 }
while (!connected_rev && (uint32_t)(PJON_MILLIS()-start) < 2000);
622 #ifdef ETCP_DEBUG_PRINT
623 Serial.println(connected_rev ? F(
"Conn rev to srv") : F(
"Failed rev conn to srv"));
626 uint32_t conn_header = htonl(ETCP_CONNECTION_HEADER_B);
627 if (_client_in.write((uint8_t*) &conn_header, 4) != 4) {
628 connected_rev =
false;
629 #ifdef ETCP_ERROR_PRINT
630 Serial.println(F(
"Disconn rev. failed write connhead"));
636 _ack_requested = _request_ack;
638 _last_receive_time = PJON_MILLIS();
645 _connection_time = PJON_MILLIS();
647 if (_single_socket) {
648 _ack_requested = _request_ack;
652 if (!connected || (reverse && !connected_rev)) {
653 #ifdef ETCP_ERROR_PRINT
654 Serial.print(F(
"Fail conn, closing "));
655 Serial.print(connected);
656 Serial.println(connected_rev);
659 _current_device = -1;
663 _current_device = id;
677 #ifdef ETCP_DEBUG_PRINT
678 if (_client_in || (_initiate_both_sockets_in_same_direction && _client_out)) {
679 Serial.println(F(
"Disconn in&rev"));
682 #ifdef ETCP_SINGLE_DIRECTION
683 if (_initiate_both_sockets_in_same_direction && _client_out) {
693 void disconnect_out()
695 #ifdef ETCP_DEBUG_PRINT
696 if (_client_out || (_initiate_both_sockets_in_same_direction && _client_in)) {
697 Serial.println(F(
"Disconn out&rev"));
703 #ifdef ETCP_SINGLE_DIRECTION
704 if (_initiate_both_sockets_in_same_direction && _client_in) {
714 bool disconnect = !_keep_connection;
715 #ifdef ETCP_SINGLE_DIRECTION
716 bool reverse = _initiate_both_sockets_in_same_direction && !_initiator;
718 if (!disconnect && _client_in && !_client_in.connected()) {
721 #ifdef ETCP_SINGLE_DIRECTION
722 if (!disconnect && reverse && _client_out && !_client_out.connected()) {
725 if (!disconnect && reverse && (!_client_in || !_client_out)) {
729 if (!disconnect && _client_in && got_receive_timeout()) {
730 #ifdef ETCP_ERROR_PRINT
731 Serial.println(F(
"Receive timeout, disconn."));
741 bool did_connect =
false, connected = _client_in;
743 _client_in = _server->available();
744 connected = _client_in;
745 #ifdef ETCP_DEBUG_PRINT
747 Serial.println(F(
"Accepted"));
751 uint32_t connection_header = 0;
752 bool header_ok =
false;
753 if (read_bytes(_client_in, (uint8_t*) &connection_header, 4) == 4) {
754 if (connection_header == htonl(ETCP_CONNECTION_HEADER_A)) {
756 _ack_requested =
false;
757 }
else if (connection_header == htonl(ETCP_CONNECTION_HEADER_A_ACK)) {
759 _ack_requested =
true;
767 #ifdef ETCP_ERROR_PRINT
768 Serial.println(F(
"Disconn. no connhead"));
775 #ifdef ETCP_SINGLE_DIRECTION
776 if (connected && reverse && !_client_out) {
777 #ifdef ETCP_DEBUG_PRINT
778 Serial.println(F(
"Lst rev"));
781 _request_ack = _ack_requested;
783 bool connected_reverse =
false;
784 uint32_t start = PJON_MILLIS();
786 _client_out = _server->available();
787 }
while (!_client_out && (uint32_t)(PJON_MILLIS()-start) < 2000);
790 #ifdef ETCP_DEBUG_PRINT
791 Serial.println(
"Accept rev OK");
793 uint32_t connection_header = 0;
794 if (read_bytes(_client_out, (uint8_t*) &connection_header, 4) == 4 &&
795 connection_header == htonl(ETCP_CONNECTION_HEADER_B)) {
796 connected_reverse =
true;
798 #ifdef ETCP_ERROR_PRINT
799 Serial.println(F(
"Disconn. rev no connhead"));
803 #ifdef ETCP_ERROR_PRINT
804 Serial.println(F(
"Accept rev timed out"));
808 if (connected_reverse) {
811 #ifdef ETCP_ERROR_PRINT
812 Serial.print(F(
"Fail accept, closing, "));
813 Serial.print(connected);
814 Serial.println(connected_reverse);
823 _connection_time = PJON_MILLIS();
825 _last_receive_time = PJON_MILLIS();
831 void disconnect_out_if_needed(uint16_t result)
834 if(_client_out && (result == PJON_FAIL || !_keep_connection)) {
836 #ifdef ETCP_DEBUG_PRINT
837 Serial.print(
"Disconn outcl. OK=");
838 Serial.println(result == PJON_ACK);
843 bool got_receive_timeout()
845 return (uint32_t)(PJON_MILLIS() - _last_receive_time) > ETCP_IDLE_TIMEOUT;
848 bool disconnect_in_if_needed()
850 if(_client_in && !_keep_connection) {
851 #ifdef ETCP_DEBUG_PRINT
852 Serial.println(
"Disc. inclient.");
863 const uint8_t *packet,
868 uint32_t head = htonl(ETCP_HEADER), foot = htonl(ETCP_FOOTER), len = htonl(length);
870 memcpy(buf, &head, 4);
871 memcpy(&buf[4], &
id, 1);
872 memcpy(&buf[5], &len, 4);
874 if (!_single_socket && _client_in)
if (_client_in.available() > 0) {
878 #ifdef HAS_ETHERNETUDP
879 bool ok = client.write((uint8_t*) buf, 9) == 9;
881 ok = client.write((uint8_t*) packet, length) == length;
884 ok = client.write((uint8_t*) &foot, 4) == 4;
890 memcpy(totalbuf(), buf, 9);
891 memcpy(&(totalbuf()[9]), packet, length);
892 memcpy(&(totalbuf()[9+length]), &foot, 4);
893 bool ok = client.write((uint8_t*)totalbuf(), 9+length+4) == (9+length+4);
898 #ifdef ETCP_DEBUG_PRINT
899 Serial.print(
"Write stat: ");
903 uint16_t result = PJON_FAIL;
908 int16_t status = read_bytes(client, (uint8_t*) &code, 2);
910 if(status == 2 && code == PJON_ACK) {
916 #ifdef ETCP_DEBUG_PRINT
917 Serial.print(
"PJON_ACK stat: ");
918 Serial.print(result == PJON_ACK);
919 Serial.println(ok ?
" OK" :
" FAIL");
922 result = ok ? PJON_ACK : PJON_FAIL;
932 #ifdef ETCP_SINGLE_SOCKET_WITH_ACK
933 uint16_t single_socket_transfer(
937 const uint8_t *contents,
943 bool connected = connect(
id);
944 #ifdef ETCP_DEBUG_PRINT
953 uint32_t head = htonl(ETCP_SINGLE_SOCKET_HEADER);
954 uint8_t numpackets_out = length > 0 ? 1 : 0;
956 memcpy(buf, &head, 4);
957 memcpy(&buf[4], &numpackets_out, 1);
959 ok = client.write((uint8_t*) &buf, 5) == 5;
966 if(ok && numpackets_out > 0) {
967 ok = send(client,
id, contents, length) == PJON_ACK;
968 #ifdef ETCP_DEBUG_PRINT
969 Serial.print(F(
"++++Sent p, ok="));
975 uint8_t numpackets_in = 0;
977 ok = read_bytes(client, &numpackets_in, 1) == 1;
979 #ifdef ETCP_DEBUG_PRINT
980 if (!ok || numpackets_in > 0) {
981 Serial.print(
"Read np_in: ");
982 Serial.print(numpackets_in);
983 Serial.println(ok ?
" OK" :
" FAIL");
988 for(uint8_t i = 0; ok && i < numpackets_in; i++) {
989 while(client.available() < 1 && client.connected()) ;
990 ok = receive(client,
true) == PJON_ACK;
991 #ifdef ETCP_DEBUG_PRINT
992 Serial.print(F(
"------->Read p "));
994 Serial.print(F(
", ok="));
1000 uint32_t foot = htonl(ETCP_SINGLE_SOCKET_FOOTER);
1002 ok = client.write((uint8_t*) &foot, 4) == 4;
1007 #ifdef ETCP_DEBUG_PRINT
1013 uint16_t result = ok ? PJON_ACK : PJON_FAIL;
1014 disconnect_out_if_needed(result);
1015 #ifdef ETCP_DEBUG_PRINT
1016 if (numpackets_in > 0 || numpackets_out > 0) {
1017 Serial.print(
"INOUTm ");
1018 Serial.print(numpackets_in);
1019 Serial.print(numpackets_out);
1020 Serial.println(ok ?
" OK" :
" FAIL");
1025 return contents == NULL ? (numpackets_in > 0 ? result : PJON_FAIL) : result;
1028 if (client && got_receive_timeout()) {
1029 #ifdef ETCP_ERROR_PRINT
1030 Serial.println(F(
"Receive timeout, disconn."));
1036 bool connected = accept();
1037 #ifdef ETCP_DEBUG_PRINT
1045 bool ok = read_until_header(client, ETCP_SINGLE_SOCKET_HEADER);
1047 _last_receive_time = PJON_MILLIS();
1049 #ifdef ETCP_DEBUG_PRINT
1055 uint8_t numpackets_in = 0;
1057 ok = read_bytes(client, (uint8_t*) &numpackets_in, 1) == 1;
1059 #ifdef ETCP_DEBUG_PRINT
1060 if (!ok || numpackets_in > 0) {
1061 Serial.print(
"Read np_in: ");
1062 Serial.print(numpackets_in);
1063 Serial.println(ok ?
" OK" :
" FAIL");
1068 for(uint8_t i = 0; ok && i < numpackets_in; i++) {
1069 while(client.available() < 1 && client.connected()) ;
1070 ok = receive(client,
true) == PJON_ACK;
1071 #ifdef ETCP_DEBUG_PRINT
1072 Serial.print(F(
"Read p "));
1074 Serial.print(F(
", ok="));
1080 uint8_t numpackets_out = length > 0 ? 1 : 0;
1082 ok = client.write((uint8_t*) &numpackets_out, 1) == 1;
1089 if(ok && numpackets_out > 0) {
1090 ok = send(client,
id, contents, length) == PJON_ACK;
1091 #ifdef ETCP_DEBUG_PRINT
1092 Serial.print(F(
"Sent p, ok="));
1100 ok = read_bytes(client, (uint8_t*) &foot, 4) == 4;
1101 if(foot != htonl(ETCP_SINGLE_SOCKET_FOOTER)) {
1104 #ifdef ETCP_DEBUG_PRINT
1111 disconnect_in_if_needed();
1113 #ifdef ETCP_DEBUG_PRINT
1114 if (numpackets_in > 0 || numpackets_out > 0) {
1115 Serial.print(
"INOUT ");
1116 Serial.print(numpackets_in);
1117 Serial.print(numpackets_out);
1118 Serial.println(ok ?
" OK" :
" FAIL");
1124 #ifdef ETCP_ERROR_PRINT
1125 Serial.print(F(
"Failure, disconnecting."));
1130 uint16_t result = ok ? PJON_ACK : PJON_FAIL;
1131 return contents == NULL ? (numpackets_in > 0 ? result : PJON_FAIL) : result;
1142 header = htonl(header);
1144 int8_t bytes_read = 0;
1145 bytes_read = (uint8_t)read_bytes(client, (uint8_t*) &head, 4);
1146 if(bytes_read != 4 || head != header) {
1153 bytes_read = (uint8_t)read_bytes(client, &((uint8_t*) &head)[3], 1);
1154 if(bytes_read != 1) {
1157 }
while(head != header);
1159 return head == header;
1188 const uint8_t remote_ip[],
1189 uint16_t port_number = ETCP_DEFAULT_PORT
1192 if (_remote_node_count == ETCP_MAX_REMOTE_NODES) {
1195 _remote_id[_remote_node_count] = remote_id;
1196 memcpy(_remote_ip[_remote_node_count], remote_ip, 4);
1197 _remote_port[_remote_node_count] = port_number;
1198 _remote_node_count++;
1199 return _remote_node_count - 1;
1209 void start_listening(uint16_t port_number = ETCP_DEFAULT_PORT)
1211 _local_port = port_number;
1213 if(_server == NULL && (!_initiate_both_sockets_in_same_direction || !_initiator)) {
1214 #ifdef ETCP_DEBUG_PRINT
1215 Serial.print(
"Lst on port ");
1216 Serial.println(port_number);
1227 void keep_connection(
bool keep)
1229 _keep_connection = keep;
1239 #ifdef ETCP_SINGLE_SOCKET_WITH_ACK
1240 void single_socket(
bool single_socket)
1242 _single_socket = single_socket;
1243 keep_connection(
true);
1255 #ifdef ETCP_SINGLE_DIRECTION
1256 void single_initiate_direction(
bool single_initiate_direction)
1258 _initiate_both_sockets_in_same_direction = single_initiate_direction;
1259 keep_connection(
true);
1269 void request_ack(
bool request_ack)
1271 _request_ack = request_ack;
1275 uint32_t get_connection_time()
const
1277 return _connection_time;
1279 uint32_t get_connection_count()
const
1281 return _connection_count;
1287 uint16_t send_with_duration(
1289 const uint8_t *packet,
1291 uint32_t duration_us
1294 uint32_t start = PJON_MICROS();
1295 uint16_t result = PJON_FAIL;
1297 result = send(
id, packet, length);
1299 result != PJON_ACK &&
1300 (uint32_t)(PJON_MICROS() - start) <= duration_us
1309 uint16_t poll_receive(uint8_t remote_id)
1313 if(_single_socket) {
1315 #ifdef ETCP_SINGLE_SOCKET_WITH_ACK
1316 return single_socket_transfer(_client_out, remote_id,
true, NULL, 0);
1329 uint8_t get_id()
const
1341 if(_server == NULL) {
1342 #if defined(ETCP_SINGLE_SOCKET_WITH_ACK) || defined(ETCP_SINGLE_DIRECTION)
1343 int16_t remote_id = _remote_node_count == 1 ? _remote_id[0] : -1;
1345 if(_single_socket) {
1349 #ifdef ETCP_SINGLE_SOCKET_WITH_ACK
1350 return single_socket_transfer(_client_out, remote_id,
true, NULL, 0);
1355 #ifdef ETCP_SINGLE_DIRECTION
1356 else if (_initiate_both_sockets_in_same_direction && _initiator) {
1358 uint16_t result = receive(_client_in,
false);
1359 disconnect_out_if_needed(PJON_ACK);
1360 disconnect_in_if_needed();
1366 if(_single_socket) {
1367 #ifdef ETCP_SINGLE_SOCKET_WITH_ACK
1368 return single_socket_transfer(_client_in, -1,
false, NULL, 0);
1378 uint16_t result = receive(_client_in, !_keep_connection);
1380 disconnect_in_if_needed();
1388 uint16_t receive(uint32_t duration_us)
1390 uint32_t start = PJON_MICROS();
1391 uint16_t result = PJON_FAIL;
1394 if (result != PJON_ACK) {
1395 PJON_DELAY_MICROSECONDS(250);
1398 result != PJON_ACK &&
1399 (uint32_t)(PJON_MICROS() - start) <= duration_us
1407 const uint8_t *packet,
1414 #ifdef ETCP_SINGLE_SOCKET_WITH_ACK
1415 return single_socket_transfer(
1416 _server ? _client_in : _client_out,
1418 _server ?
false :
true,
1427 bool connected =
false;
1428 #ifdef ETCP_SINGLE_DIRECTION
1429 if (_initiate_both_sockets_in_same_direction && !_initiator) {
1430 connected = accept();
1433 connected = connect(
id);
1436 uint16_t result = PJON_FAIL;
1438 result = send(_client_out,
id, packet, length);
1442 disconnect_out_if_needed(result);
1454 uint8_t acquire_id()
1460 void set_error(link_error e)
1466 void set_id(uint8_t
id)
1472 void set_receiver(link_receiver r,
void *callback_object)
1475 _callback_object = callback_object;