aboutsummaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'server.c')
-rw-r--r--server.c117
1 files changed, 110 insertions, 7 deletions
diff --git a/server.c b/server.c
index 629d976..290739e 100644
--- a/server.c
+++ b/server.c
@@ -19,6 +19,7 @@
*/
#include "joshua.h"
+#include "util.h"
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
@@ -29,10 +30,11 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
-
+#define DEFAULT_PORT 23
int server_socket;
uint16_t port;
int pipes[FD_SETSIZE][2];
+struct connection_data_t connection_data[FD_SETSIZE];
int make_server_socket(uint16_t port)
{
int sock;
@@ -40,7 +42,7 @@ int make_server_socket(uint16_t port)
sock=socket(AF_INET, SOCK_STREAM, 0);
if(sock<0)
{
- printf("error creating socket.\n");
+ printf("error opening socket.\n");
return -1;
}
name.sin_family=AF_INET;
@@ -56,7 +58,7 @@ int make_server_socket(uint16_t port)
}
int process_data(int fd)
{
- char buf[1024];
+ unsigned char buf[1024];
memset(buf, 0, sizeof(buf));
int ret=read(fd, buf, sizeof(buf));
char ctrl_c[]={0xff, 0xf4, 0xff, 0xfd, 0x06, 0x00};
@@ -78,7 +80,91 @@ int process_data(int fd)
else
{
printf("Client sends: %s\n", buf);
- write(pipes[fd][1], buf, strlen(buf));
+ if(strlen(buf)>0)
+ {
+ if(buf[0]==0xff)
+ {
+ printf("String is command.\n");
+ printf("Hex dump: ");
+ for(int i=0;buf[i];++i)
+ {
+ printf("%d ", buf[i]);
+ }
+ if(strlen(buf)<2)
+ {
+ printf("Bad command (length<3).\n");
+ return 0; /* not a fatal error */
+ }
+ unsigned char cmd=buf[1];
+#define WILL 251
+#define WONT 252
+#define DO 253
+#define DONT 254
+#define SB 250
+#define SE 240
+#define AYT 246
+#define NAWS 31
+ unsigned char opt=(strlen(buf)==2)?0:buf[2];
+ unsigned char nop[2]={0xff, 241};
+ switch(cmd)
+ {
+ case AYT:
+ /* respond with IAC NOP */
+ write(fd, nop, 2);
+ break;
+ case WILL:
+ case DO:
+ if(cmd==NAWS)
+ {
+ printf("Client offers NAWS\n");
+ }
+ else if(cmd==1)
+ {
+ printf("Client offers echo.\n");
+ }
+ break;
+ case WONT:
+ case DONT:
+ if(cmd==NAWS)
+ {
+ printf("Client denies NAWS.\n");
+ }
+ else if(cmd==1)
+ {
+ printf("Client denies echo.\n");
+ }
+ break;
+ default:
+ printf("Unknown command.\n");
+ break;
+ }
+ if(cmd==SB)
+ {
+ if(opt==NAWS)
+ {
+ if(strlen(buf)>=9)
+ {
+ uint16_t width, height;
+ uint8_t width_hi, width_lo, height_hi, height_lo;
+ width_hi=buf[3];
+ width_lo=buf[4];
+ height_hi=buf[5];
+ height_lo=buf[6];
+ width=(width_hi<<8)|width_lo;
+ height=(height_hi<<8)|height_lo;
+ connection_data[fd].know_termsize=(width==0 || height==0)?0:1; /* if any dimension is zero, unknown */
+ connection_data[fd].term_height=height;
+ connection_data[fd].term_width=width;
+ printf("Client window is %dx%d\n", width, height);
+ }
+ }
+ }
+ }
+ else
+ {
+ write(pipes[fd][1], buf, strlen(buf));
+ }
+ }
return 0;
}
}
@@ -88,14 +174,29 @@ void serv_cleanup()
fflush(stdout);
shutdown(server_socket, SHUT_RDWR);
}
+void setup_new_connection(int fd)
+{
+ unsigned char will_naws[]={0xff, 251, 31};
+ write(fd, will_naws, sizeof(will_naws));
+ memset(&connection_data[fd], 0, sizeof(struct connection_data_t));
+}
int main(int argc, char* argv[])
{
if(argc!=2)
{
- printf("Usage: %s PORT\n", argv[0]);
- return 2;
+ printf("Listening on default port: %d\n", DEFAULT_PORT);
+ port=DEFAULT_PORT;
+ }
+ else
+ {
+ int port2=atoi(argv[1]);
+ if(port2<0 || port2>65535)
+ {
+ printf("Port out of range.\n");
+ return 2;
+ }
+ port=atoi(argv[1]);
}
- port=atoi(argv[1]);
printf("Initializing server on port %u...\n", port);
signal(SIGINT, &serv_cleanup);
int sock=make_server_socket(port);
@@ -144,6 +245,8 @@ int main(int argc, char* argv[])
pid_t pid=fork();
if(pid==0) /* child */
{
+ /* set up the connection */
+ setup_new_connection(new);
be_joshua(new);
printf("Client exits\n");
shutdown(new, SHUT_RDWR);