add server
This commit is contained in:
commit
373303723b
210
server.c
Normal file
210
server.c
Normal file
@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Simple bsdsocket.library server for AmigaOS
|
||||
* Copyright 2022 John Bintz
|
||||
* Released under the MIT License
|
||||
* Visit theindustriousrabbit.com for more fun!
|
||||
*
|
||||
* You would not believe how sparse the documentation for
|
||||
* bsdsocket.library is on the Amiga. All this required
|
||||
* digging through documentation on multiple sites, in
|
||||
* multiple forum threads to describe the Amiga quirks
|
||||
* (Amiga code has quirks? who knew!), and required a bunch of
|
||||
* experimentation and resetting the Minimig MiSTer core
|
||||
* and PPP connection to get this working. I tested it
|
||||
* with CodeWatcher and nothing is leaking, so this should
|
||||
* be a (hopefully) good bsdsocket example in C for the Amiga.
|
||||
*
|
||||
* This code is built for SAS/C. Be sure to disable ChkAbort
|
||||
* in the Linker options, otherwise the SAS/C Ctrl-c
|
||||
* handler will take over and screw up server teardown.
|
||||
*
|
||||
* You can use netcat/ncat on another machine to send data
|
||||
* to the running server:
|
||||
*
|
||||
* echo "whoa computers" | netcat 192.168.50.100 8090
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <proto/exec.h>
|
||||
#include <dos/dos.h>
|
||||
|
||||
#include <proto/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
// socket stuff
|
||||
struct Library *SocketBase;
|
||||
int serverSocket = -1;
|
||||
struct sockaddr_in serverAddress;
|
||||
|
||||
#define PORT (8090)
|
||||
#define MAX_CONNECTIONS (2)
|
||||
|
||||
// data handling
|
||||
#define BUFFER_LENGTH (256)
|
||||
char buffer [BUFFER_LENGTH];
|
||||
int msgSize;
|
||||
|
||||
// set up all the global stuff we need, allowing for early exits
|
||||
// on failures.
|
||||
int setup(void) {
|
||||
const int enable = 1;
|
||||
|
||||
// this works with the most modern MiamiDX
|
||||
if (!(SocketBase = OpenLibrary("bsdsocket.library", 4))) {
|
||||
printf("Can't open socket library\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
serverSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (serverSocket < 0) {
|
||||
printf("can't get a socket\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// AmiTCP 4.3 SDK does not have SO_REUSEPORT, this is all you get
|
||||
if (setsockopt(
|
||||
serverSocket,
|
||||
SOL_SOCKET,
|
||||
SO_REUSEADDR,
|
||||
// oh c...
|
||||
&enable,
|
||||
sizeof(int)
|
||||
) < 0) {
|
||||
printf("can't set socket options\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void teardown(void) {
|
||||
if (serverSocket != -1) {
|
||||
|
||||
shutdown(
|
||||
serverSocket,
|
||||
// SHUT_RDWR, stop all communication both ways
|
||||
2
|
||||
);
|
||||
// double close it to stop the listen as well
|
||||
CloseSocket(serverSocket);
|
||||
CloseSocket(serverSocket);
|
||||
}
|
||||
|
||||
if (SocketBase) {
|
||||
CloseLibrary(SocketBase);
|
||||
}
|
||||
}
|
||||
|
||||
int startServer(void) {
|
||||
// bind to all addresses on our defined port
|
||||
memset(&serverAddress, 0, sizeof(serverAddress));
|
||||
serverAddress.sin_family = AF_INET;
|
||||
serverAddress.sin_port = htons(PORT);
|
||||
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (bind(
|
||||
serverSocket,
|
||||
(struct sockaddr *) &serverAddress,
|
||||
sizeof(serverAddress)
|
||||
) < 0) {
|
||||
printf("can't bind\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (listen(serverSocket, MAX_CONNECTIONS) < 0) {
|
||||
printf("can't listen\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void readData(int clientSocket) {
|
||||
do {
|
||||
// keep stomping over the same buffer
|
||||
// ideally we'd take the data out of the buffer and
|
||||
// do something with it.
|
||||
msgSize = recv(clientSocket, buffer, BUFFER_LENGTH, 0);
|
||||
|
||||
if (msgSize <= 0) {
|
||||
printf("End of data\n");
|
||||
} else {
|
||||
printf("Got stuff: %i\n", msgSize);
|
||||
printf("%s\n", buffer);
|
||||
}
|
||||
} while (msgSize == 256);
|
||||
printf("Data received: %s\n", buffer);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// The incoming netcat client
|
||||
int clientSocket;
|
||||
struct sockaddr_in clientAddress;
|
||||
LONG clientLength = sizeof(clientAddress);
|
||||
|
||||
// be able to use WaitSelect
|
||||
int waitSelectResult;
|
||||
fd_set readFDs;
|
||||
|
||||
if (setup() != 0) {
|
||||
teardown();
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("got socket number %d\n", serverSocket);
|
||||
|
||||
if (startServer() != 0) {
|
||||
teardown();
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("listening on port %d\n", PORT);
|
||||
|
||||
// just enough to get WaitSelect working
|
||||
// this macro also wants strings.h included
|
||||
FD_ZERO(&readFDs); ((
|
||||
FD_SET(serverSocket, &readFDs);
|
||||
waitSelectResult = WaitSelect(
|
||||
serverSocket + 1,
|
||||
&readFDs,
|
||||
NULL, NULL, NULL,
|
||||
// other Exec Signals would go here as ORed mp_SigBits
|
||||
NULL
|
||||
);
|
||||
|
||||
// WaitSelect will trap on Ctrl-C for us, and returns -1 if that happens
|
||||
if (waitSelectResult == -1) {
|
||||
printf("ctrl-c\n");
|
||||
teardown();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (
|
||||
(
|
||||
clientSocket = accept(
|
||||
serverSocket,
|
||||
(struct sockaddr *) &clientAddress,
|
||||
&clientLength
|
||||
)
|
||||
) < 0
|
||||
) {
|
||||
printf("can't accept\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// note the capitalization difference on Inet_NtoA. the Amiga does
|
||||
// that a lot...
|
||||
printf("connection from %s\n", Inet_NtoA(clientAddress.sin_addr.s_addr));
|
||||
|
||||
readData(clientSocket);
|
||||
|
||||
printf("all done\n");
|
||||
|
||||
teardown();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user