use Network framework for LocalTalk over TCP
This commit is contained in:
parent
c2f2622cb5
commit
54f6496031
|
@ -20,21 +20,6 @@
|
|||
|
||||
#define TCP_dolog (dbglog_HAVE && 0)
|
||||
|
||||
#ifndef use_winsock
|
||||
#define use_winsock 0
|
||||
#endif
|
||||
|
||||
#if use_winsock
|
||||
#define my_INVALID_SOCKET INVALID_SOCKET
|
||||
#define my_SOCKET SOCKET
|
||||
#define my_closesocket closesocket
|
||||
#define socklen_t int
|
||||
#else
|
||||
#define my_INVALID_SOCKET (-1)
|
||||
#define my_SOCKET int
|
||||
#define my_closesocket close
|
||||
#endif
|
||||
|
||||
#if TCP_dolog
|
||||
LOCALPROC dbglog_writeSockErr(char *s)
|
||||
{
|
||||
|
@ -55,52 +40,46 @@ LOCALPROC dbglog_writeSockErr(char *s)
|
|||
/*
|
||||
Transmit buffer for localtalk data and its metadata
|
||||
*/
|
||||
LOCALVAR ui3b tx_buffer[6 + LT_TxBfMxSz] =
|
||||
"LLpppp";
|
||||
|
||||
LOCALVAR ui3b tx_buffer[6 + LT_TxBfMxSz] = "LLpppp";
|
||||
|
||||
/*
|
||||
Receive buffer for LocalTalk data and its metadata
|
||||
*/
|
||||
LOCALVAR unsigned int rx_buffer_allocation = 1800;
|
||||
|
||||
LOCALVAR my_SOCKET sock_fd = my_INVALID_SOCKET;
|
||||
LOCALVAR blnr tcp_ok = falseblnr;
|
||||
LOCALVAR nw_connection_t connection = nil;
|
||||
LOCALVAR NSData *nextPacket;
|
||||
|
||||
#if use_winsock
|
||||
LOCALVAR blnr have_winsock = falseblnr;
|
||||
#endif
|
||||
void welcome_next_packet(void)
|
||||
{
|
||||
// schedule receiving length
|
||||
nw_connection_receive(connection, 2, 2, ^(dispatch_data_t _Nullable content, nw_content_context_t _Nullable context, bool is_complete, nw_error_t _Nullable error) {
|
||||
uint8_t buf[2];
|
||||
if (error != nil) {
|
||||
NSLog(@"ERROR RECEIVING LENGTH: %@", error);
|
||||
return;
|
||||
}
|
||||
[(NSData*)content getBytes:buf length:2];
|
||||
uint16_t length = (buf[0] << 8) | buf[1];
|
||||
|
||||
// schedule receiving packet
|
||||
nw_connection_receive(connection, (uint32_t)length, (uint32_t)length, ^(dispatch_data_t _Nullable content, nw_content_context_t _Nullable context, bool is_complete, nw_error_t _Nullable error) {
|
||||
if (error != nil) {
|
||||
NSLog(@"ERROR RECEIVING DATA: %@", error);
|
||||
return;
|
||||
}
|
||||
nextPacket = (NSData*)content;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
LOCALPROC start_tcp(void)
|
||||
{
|
||||
#if use_winsock
|
||||
WSADATA wsaData;
|
||||
#endif
|
||||
struct sockaddr_in addr;
|
||||
|
||||
#if use_winsock
|
||||
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) {
|
||||
#if TCP_dolog
|
||||
dbglog_writeln("WSAStartup fails");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
have_winsock = trueblnr;
|
||||
#endif
|
||||
|
||||
if (my_INVALID_SOCKET == (sock_fd =
|
||||
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
|
||||
{
|
||||
#if TCP_dolog
|
||||
dbglog_writeSockErr("socket");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* find server from LTOVRTCP_SERVER env, should be in the form 1.2.3.4:12345 */
|
||||
char *server = NULL;
|
||||
char buf[32];
|
||||
short port = 0;
|
||||
char *portStr = NULL;
|
||||
if ((server = getenv("LTOVRTCP_SERVER")) && strlen(server) < sizeof(buf)) {
|
||||
strcpy(buf, server);
|
||||
char *separator = strchr(buf, ':');
|
||||
|
@ -111,6 +90,7 @@ LOCALPROC start_tcp(void)
|
|||
separator++;
|
||||
if (strlen(separator) > 1) {
|
||||
port = (short)atoi(separator);
|
||||
portStr = separator;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,42 +99,17 @@ LOCALPROC start_tcp(void)
|
|||
}
|
||||
|
||||
/* connect to server */
|
||||
memset((char*)&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr(buf);
|
||||
addr.sin_port = htons(port);
|
||||
#if ! use_winsock
|
||||
errno = 0;
|
||||
#endif
|
||||
if (0 != connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr))) {
|
||||
#if TCP_dolog
|
||||
dbglog_writeSockErr("connect");
|
||||
#endif
|
||||
MacMsg("Could not connect to LocalTalk server", strerror(errno), falseblnr);
|
||||
return;
|
||||
}
|
||||
#if TCP_dolog
|
||||
dbglog_writeln("tcp connected");
|
||||
#endif
|
||||
|
||||
/* non-blocking I/O is good for the soul */
|
||||
#if use_winsock
|
||||
{
|
||||
int iResult;
|
||||
u_long iMode = 1;
|
||||
|
||||
iResult = ioctlsocket(sock_fd, FIONBIO, &iMode);
|
||||
if (iResult != NO_ERROR) {
|
||||
/*
|
||||
printf("ioctlsocket failed with error: %ld\n", iResult);
|
||||
*/
|
||||
}
|
||||
}
|
||||
#else
|
||||
fcntl(sock_fd, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
tcp_ok = trueblnr;
|
||||
nw_endpoint_t endpoint = nw_endpoint_create_host(buf, portStr);
|
||||
nw_parameters_t params = nw_parameters_create_secure_tcp(NW_PARAMETERS_DISABLE_PROTOCOL, ^(nw_protocol_options_t _Nonnull options) {
|
||||
nw_tcp_options_set_no_delay(options, true);
|
||||
});
|
||||
connection = nw_connection_create(endpoint, params);
|
||||
nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t _Nullable error) {
|
||||
NSLog(@"connection state %@: %@", @[@"invalid", @"waiting", @"preparing", @"ready", @"failed", @"cancelled"][state], error);
|
||||
});
|
||||
nw_connection_set_queue(connection, dispatch_get_main_queue());
|
||||
nw_connection_start(connection);
|
||||
welcome_next_packet();
|
||||
}
|
||||
|
||||
LOCALVAR unsigned char *MyRxBuffer = NULL;
|
||||
|
@ -166,7 +121,6 @@ LOCALVAR unsigned char *MyRxBuffer = NULL;
|
|||
LOCALFUNC blnr InitLocalTalk(void)
|
||||
{
|
||||
LT_PickStampNodeHint();
|
||||
|
||||
LT_TxBuffer = &tx_buffer[6];
|
||||
|
||||
MyRxBuffer = malloc(rx_buffer_allocation);
|
||||
|
@ -183,23 +137,7 @@ LOCALFUNC blnr InitLocalTalk(void)
|
|||
|
||||
LOCALPROC UnInitLocalTalk(void)
|
||||
{
|
||||
if (my_INVALID_SOCKET != sock_fd) {
|
||||
if (0 != my_closesocket(sock_fd)) {
|
||||
#if TCP_dolog
|
||||
dbglog_writeSockErr("my_closesocket sock_fd");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if use_winsock
|
||||
if (have_winsock) {
|
||||
if (0 != WSACleanup()) {
|
||||
#if TCP_dolog
|
||||
dbglog_writeSockErr("WSACleanup");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nw_connection_cancel(connection);
|
||||
|
||||
if (NULL != MyRxBuffer) {
|
||||
free(MyRxBuffer);
|
||||
|
@ -238,25 +176,19 @@ LOCALPROC embedMyPID(void)
|
|||
|
||||
GLOBALOSGLUPROC LT_TransmitPacket(void)
|
||||
{
|
||||
size_t bytes;
|
||||
/* Write the packet to TCP */
|
||||
#if TCP_dolog
|
||||
dbglog_writeln("writing to tcp");
|
||||
#endif
|
||||
embedPacketLength(LT_TxBuffSz + 4);
|
||||
embedMyPID();
|
||||
if (tcp_ok) {
|
||||
|
||||
bytes = send(sock_fd,
|
||||
(const void *)tx_buffer, LT_TxBuffSz + 6, 0);
|
||||
#if TCP_dolog
|
||||
dbglog_writeCStr("sent ");
|
||||
dbglog_writeNum(bytes);
|
||||
dbglog_writeCStr(" bytes");
|
||||
dbglog_writeReturn();
|
||||
#endif
|
||||
(void) bytes; /* avoid warning about unused */
|
||||
}
|
||||
char *buf = malloc(LT_TxBfMxSz + 6);
|
||||
memcpy(buf, tx_buffer, LT_TxBfMxSz + 6);
|
||||
dispatch_data_t data = dispatch_data_create(buf, LT_TxBuffSz + 6, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_FREE);
|
||||
nw_connection_send(connection, data, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^(nw_error_t _Nullable error) {
|
||||
if (error) {
|
||||
NSLog(@"nw_connection_send error %@", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -305,68 +237,18 @@ LOCALFUNC int packetIsOneISent(void)
|
|||
|
||||
LOCALFUNC int GetNextPacket(void)
|
||||
{
|
||||
unsigned char* device_buffer = MyRxBuffer;
|
||||
if (tcp_ok == falseblnr)
|
||||
{
|
||||
if (nextPacket == nil) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if ! use_winsock
|
||||
errno = 0;
|
||||
#endif
|
||||
/* peek length */
|
||||
ssize_t bytes = recv(sock_fd, (void *)device_buffer, 2, MSG_PEEK);
|
||||
if (bytes == 2)
|
||||
{
|
||||
int incoming_length = (device_buffer[0] << 8) + device_buffer[1];
|
||||
bytes = recv(sock_fd, (void*)device_buffer, 2 + incoming_length, MSG_PEEK);
|
||||
if (bytes == 2 + incoming_length)
|
||||
{
|
||||
/* read the packet */
|
||||
bytes = recv(sock_fd, (void*)device_buffer, 2 + incoming_length, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes < 0) {
|
||||
#if use_winsock
|
||||
if (WSAEWOULDBLOCK != WSAGetLastError())
|
||||
#else
|
||||
if (ECONNRESET == errno || ETIMEDOUT == errno)
|
||||
{
|
||||
MacMsg("Lost connection to LocalTalk server", strerror(errno), falseblnr);
|
||||
#if TCP_dolog
|
||||
dbglog_writeCStr("tcp error ");
|
||||
dbglog_writeCStr(strerror(errno));
|
||||
dbglog_writeReturn();
|
||||
#endif
|
||||
tcp_ok = falseblnr;
|
||||
my_closesocket(sock_fd);
|
||||
sock_fd = my_INVALID_SOCKET;
|
||||
}
|
||||
else if (EAGAIN != errno)
|
||||
#endif
|
||||
{
|
||||
#if TCP_dolog
|
||||
dbglog_writeCStr("ret");
|
||||
dbglog_writeNum(bytes);
|
||||
dbglog_writeCStr(", bufsize ");
|
||||
dbglog_writeNum(rx_buffer_allocation);
|
||||
#if ! use_winsock
|
||||
dbglog_writeCStr(", errno = ");
|
||||
dbglog_writeCStr(strerror(errno));
|
||||
#endif
|
||||
dbglog_writeReturn();
|
||||
#endif
|
||||
}
|
||||
int bytes = (int)nextPacket.length;
|
||||
if (bytes <= rx_buffer_allocation) {
|
||||
[nextPacket getBytes:MyRxBuffer length:bytes];
|
||||
} else {
|
||||
#if TCP_dolog
|
||||
dbglog_writeCStr("got ");
|
||||
dbglog_writeNum(bytes);
|
||||
dbglog_writeCStr(", bufsize ");
|
||||
dbglog_writeNum(rx_buffer_allocation);
|
||||
dbglog_writeReturn();
|
||||
#endif
|
||||
bytes = 0;
|
||||
}
|
||||
nextPacket = nil;
|
||||
welcome_next_packet();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
@ -392,12 +274,12 @@ label_retry:
|
|||
{
|
||||
#if TCP_dolog
|
||||
dbglog_writeCStr("passing ");
|
||||
dbglog_writeNum(bytes - 6);
|
||||
dbglog_writeNum(bytes - 4);
|
||||
dbglog_writeCStr(" bytes to receiver");
|
||||
dbglog_writeReturn();
|
||||
#endif
|
||||
LT_RxBuffer = MyRxBuffer + 6;
|
||||
LT_RxBuffSz = bytes - 6;
|
||||
LT_RxBuffer = MyRxBuffer + 4;
|
||||
LT_RxBuffSz = bytes - 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,8 +112,7 @@ LOCALPROC dbglog_close0(void) {
|
|||
#include "PBUFSTDC.h"
|
||||
|
||||
#if EmLocalTalk
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#import <Network/Network.h>
|
||||
#include "LTOVRTCP.h"
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue