int Init_CONNECT(client_t *client, textbuf *buf, CTP_head_t head) { /* get the message body */ CTP_CONNECT_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check version: only support current version */ if (mesg.version != PROTOCOL_VERSION) { free_mesg(mesg); err_and_close(client, UNSUPPORTED_VERSION); return 0; } free_mesg(mesg); /* transient... */ client->state = Version; /* build ACKCONNECT response */ CTP_ACKCONNECT_t response; response.version = PROTOCOL_VERSION; response.client_id = client->id; response.options = new_options(); /* send response */ rv = send_ACKCONNECT(client->sockfd, response); free_options(response.options); client->state = Connected; return rv; }
int Any_SYNC(client_t *client, textbuf *buf, CTP_head_t head) { client_t c; CTP_MOVE_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check for correct client id */ if (mesg.client_id != client->id) { free_mesg(mesg); return -1; } free_mesg(mesg); /* get STATUS response */ CTP_STATUS_t response = get_STATUS(buf); /* send response */ rv = send_STATUS(client->sockfd, response); free_options(response.options); return rv; }
/* * Have an exchange with the server over TCP/IP and get the IPs of our local * and the remote host. */ static void client_get_hosts(char *lhost, char *rhost) { SS raddr; socklen_t rlen; char *service; uint32_t port; int fd = -1; recv_mesg(&port, sizeof(port), "TCP IPv4 server port"); port = decode_uint32(&port); service = qasprintf("%d", port); connect_tcp(ServerName, service, &raddr, &rlen, &fd); free(service); get_socket_ip((SA *)&raddr, rlen, rhost, NI_MAXHOST); send_mesg(rhost, NI_MAXHOST, "server IP"); recv_mesg(lhost, NI_MAXHOST, "client IP"); close(fd); }
/* While this is invalid, we may still get it in this state from a * well-behaved client if we send a SERVRELEASE at about the same * time the client sends an EDIT. So we reject it and continue. */ int Open_EDIT(client_t *client, textbuf *buf, CTP_head_t head) { CTP_EDIT_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; rv = send_err(client, REJECT_EDIT); free_mesg(mesg); return rv; }
int Connected_OPEN(client_t *client, textbuf *buf, CTP_head_t head) { CTP_OPEN_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check for correct client id */ if (mesg.client_id != client->id) { free_mesg(mesg); return -1; } /* check file id * this server only supports a "default" file */ if (mesg.file_id != 0) { free_mesg(mesg); send_err(client, BAD_FILE_ID); return 1; } free_mesg(mesg); /* transient... */ client->state = Opening; /* build ACKOPEN response */ CTP_ACKOPEN_t response; response.options = new_options(); /* send response */ rv = send_ACKOPEN(client->sockfd, response); free_options(response.options); client->state = Open; if (rv < 1) return rv; /* send STATUS message to all clients */ CTP_STATUS_t status = get_status(buf); client_t *c; for (c = clients; c <= max_active_client; ++c) { if (c->active) send_STATUS(c->sockfd, status); } free_options(status.options); return 1; }
int Locked_EDIT(client_t *client, textbuf *buf, CTP_head_t head) { CTP_EDIT_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check for correct client id */ if (mesg.client_id != client->id) { free_mesg(mesg); return -1; } switch (mesg.edit_action) { case INS: rv = tboverwrite(buf, mesg.pos, 0, mesg.data, mesg.datalen); break; case OVR: rv = tboverwrite(buf, mesg.pos, mesg.len, mesg.data, mesg.datalen); break; case DEL: rv = tboverwrite(buf, mesg.pos, mesg.len, NULL, 0); break; } if (rv < 0) { /* reject the edit */ free_mesg(mesg); rv = send_err(client, REJECT_EDIT); } else { /* prepare and send ACKEDIT */ CTP_ACKEDIT_t response; response.options = new_options(); rv = send_ACKEDIT(client->sockfd, response); free_options(response.options); /* relay EDIT to other clients */ client_t *c; for (c = clients; c <= max_active_client; ++c) { if (c != client && c->active) send_EDIT(c->sockfd, mesg); } } free_mesg(mesg); return rv; }
int Locked_RELEASE(client_t *client, textbuf *buf, CTP_head_t head) { CTP_RELEASE_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check for correct client id */ if (mesg.client_id != client->id) { free_mesg(mesg); return -1; } free_mesg(mesg); client->state = Open; return 1; }
int Open_REQCONTENTS(client_t *client, textbuf *buf, CTP_head_t head) { CTP_REQCONTENTS_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check for correct client id */ if (mesg.client_id != client->id) { free_mesg(mesg); return -1; } /* TODO implement IfChanged option handling */ /* Len of 0 -> until end of file */ if (mesg.len == 0) mesg.len = buf->size; /* cap pos and len to buffer size */ unsigned int pos = MIN(mesg.pos, buf->size); unsigned int len = MIN(mesg.len, buf->size - pos); free_mesg(mesg); unsigned int chunk, numChunks = len / CHUNKSIZE + 1; CTP_CONTENTS_t contents; contents.totallen = buf->size; for (chunk = 0; chunk < numChunks; ++chunk) { char databuf[CHUNKSIZE]; /* TODO consider placement */ contents.pos = pos + CHUNKSIZE * chunk; contents.datalen = tbread(buf, databuf, contents.pos, CHUNKSIZE); contents.data = databuf; rv = send_CONTENTS(client->sockfd, contents); if (rv < 1) return rv; } return 1; }
/* * Initialize and return open socket. */ static int init(void) { int sockfd; uint32_t lport; uint32_t rport; char lhost[NI_MAXHOST]; char rhost[NI_MAXHOST]; if (is_client()) client_get_hosts(lhost, rhost); else server_get_hosts(lhost, rhost); sockfd = rds_socket(lhost, Req.port); lport = get_socket_port(sockfd); encode_uint32(&lport, lport); send_mesg(&lport, sizeof(lport), "RDS port"); recv_mesg(&rport, sizeof(rport), "RDS port"); rport = decode_uint32(&rport); rds_makeaddr(&RAddr, &RLen, rhost, rport); return sockfd; }
static int check_socket(server *s, time_t t) { /* Check the status of the server's socket */ ssize_t count; char recv_buff[BUFFSIZE]; /* Consume all input on the socket */ while (s->soc >= 0 && (count = read(s->soc, recv_buff, BUFFSIZE)) >= 0) { if (count == 0) { server_disconnect(s, 1, 0, "Remote hangup"); break; } /* Set time since last message */ s->latency_time = t; s->latency_delta = 0; recv_mesg(recv_buff, count, s); } /* Server received ERROR message or remote hangup */ if (s->soc < 0) return 0; /* Socket is non-blocking, all other errors cause a disconnect */ if (errno != EWOULDBLOCK && errno != EAGAIN) { if (errno) server_disconnect(s, 1, 0, strerror(errno)); else server_disconnect(s, 1, 0, "Remote hangup"); } return 0; }
/* * Have an exchange with the client over TCP/IP and get the IP of our local * host. */ static void server_get_hosts(char *lhost, char *rhost) { int fd, lfd; uint32_t port; struct sockaddr_in laddr, raddr; socklen_t rlen; lfd = socket(AF_INET, SOCK_STREAM, 0); if (lfd < 0) error(SYS, "socket failed"); setsockopt_one(lfd, SO_REUSEADDR); memset(&laddr, 0, sizeof(laddr)); laddr.sin_family = AF_INET; laddr.sin_addr.s_addr = INADDR_ANY; laddr.sin_port = htons(0); if (bind(lfd, (SA *)&laddr, sizeof(laddr)) < 0) error(SYS, "bind INET failed"); port = get_socket_port(lfd); encode_uint32(&port, port); send_mesg(&port, sizeof(port), "TCP IPv4 server port"); if (listen(lfd, 1) < 0) error(SYS, "listen failed"); rlen = sizeof(raddr); fd = accept(lfd, (SA *)&raddr, &rlen); if (fd < 0) error(SYS, "accept failed"); close(lfd); get_socket_ip((SA *)&raddr, rlen, rhost, NI_MAXHOST); send_mesg(rhost, NI_MAXHOST, "client IP"); recv_mesg(lhost, NI_MAXHOST, "server IP"); close(fd); }
int Open_REQLOCK(client_t *client, textbuf *buf, CTP_head_t head) { CTP_OPEN_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check for correct client id */ if (mesg.client_id != client->id) { free_mesg(mesg); return -1; } /* only one client may lock at a time */ if (locking_client != NULL) { free_mesg(mesg); send_err(client, CANT_LOCK); return 1; } free_mesg(mesg); /* transient... */ client->state = WaitLock; /* build ACKLOCK response */ CTP_ACKLOCK_t response; response.options = new_options(); /* send response */ rv = send_ACKOPEN(client->sockfd, response); free_options(response.options); client->state = Locked; locking_client = client; return rv; }
int Any_MOVE(client_t *client, textbuf *buf, CTP_head_t head) { client_t c; CTP_MOVE_t mesg; int rv = recv_mesg(client->sockfd, &mesg, head); if (rv < 1) return rv; /* check for correct client id */ if (mesg.client_id != client->id) { free_mesg(mesg); return -1; } /* relay to all other clients */ for (c = clients; c <= max_active_client; ++c) if (c != client && c->active) send_MOVE(c->sockfd, mesg); free_mesg(mesg); return 1; }
icycle() { int op,a1,a2,x1,x2,i1,i2,setting,setmask,onemask,oldmask; int ecd; /* Error Code */ /* setjmp(svstck) to save stack for return */ /* from possible segment and page faults */ if((ecd=setjmp(svstck)) != 0) { goto except; } ir = pm[cmap(pc)]; pc++; /* extract instruction fields into op, a1, a2; */ /* generate the eff. virtual addresses v1, v2 */ /* using the algorithm in the Reference Manual */ op = extract(ir,24,6); a1 = extract(ir,12,10); a2 = extract(ir,0,10); x1 = extract(ir,22,1); x2 = extract(ir,10,1); i1 = extract(ir,23,1); i2 = extract(ir,11,1); v1 = a1; v2 = a2; /* address field forms initial value */ if (i1 == 1) v1 = pm[dmap(v1)]; /* if indirection, get ind. loc */ if (i2 == 1) v2 = pm[dmap(v2)]; if (x1 == 1) v1 = v1 + xr; /* if indexing specified, add xr */ if (x2 == 1) v2 = v2 + xr; switch(op) { case 1: gr = pm[dmap(v1)]; /* gr load */ break; case 2: pm[dmap(v1)] = gr; /* gr store */ break; case 3: xr = pm[dmap(v1)]; /* xr load */ break; case 4: pm[dmap(v1)] = xr; /* xr store */ break; case 5: sr = pm[dmap(v1)]; /* sr load */ break; case 6: pm[dmap(v1)] = sr; /* sr store */ break; case 8: pm[dmap(v2)] = pm[dmap(v1)]; /* copy */ break; case 9: pm[dmap(v2)] += pm[dmap(v1)]; /* add */ break; case 10: pm[dmap(v2)] -= pm[dmap(v1)]; /* subtract */ break; case 11: pm[dmap(v2)] *= pm[dmap(v1)]; /* multiply */ break; case 12: /* Divide */ if (pm[dmap(v1)] == 0) { ecd = ARITFLT; printf ("\nDivide Fault\n"); goto except; } else pm[dmap(v2)] /= pm[dmap(v1)]; break; case 13: pm[dmap(v2)] &= pm[dmap(v1)]; /* and */ break; case 14: pm[dmap(v2)] |= pm[dmap(v1)]; /* or */ break; case 16: pc = v1; /* go to */ break; case 17: if (pm[dmap(v1)] != pm[dmap(v2)]) pc++; /* if = */ break; case 18: if (pm[dmap(v1)] == pm[dmap(v2)]) pc++; /* if != */ break; case 19: if (pm[dmap(v1)] >= pm[dmap(v2)]) pc++; /* if < */ break; case 20: if (pm[dmap(v1)] < pm[dmap(v2)]) pc++; /* if >= */ break; case 21: xr++; /* loop */ if (xr < pm[dmap(v1)]) pc = v2; break; case 22: sr = pc; pc = v1; /* call */ break; case 23: pc = sr + pm[dmap(v1)]; /* return */ break; case 26: xr = v1; /* xr set */ break; case 27: pm[dmap(v2)] = v1; /* vm set */ break; case 28: pm[dmap(v2)] = extract(pm[dmap(v1 + gr/4)],(gr%4)*8,8); /* get byte */ break; case 29: setting = extract(pm[dmap(v2)],0, 8); /* set byte */ /* Byte want to set in pos with 0s other */ setmask = setting << (gr%4)*8; onemask = 0xFFFFFFFF - (0xFF << (gr%4) * 8); /* mask with ones 'cept 0's in pos. */ oldmask = pm[dmap(v1+(gr/4))] & onemask; /* old value of word with 0's in pos */ pm[dmap(v1+(gr/4))] = oldmask | setmask; /* new word to write to memory */ break; case 31: ; /* noop */ break; case 32: hlt = TRUE; /* halt */ break; case 33: /* error */ hlt = TRUE; /* A1 serves as error code */ printf("\n ERROR: %x\n",a1); break; case 34: /* PmVmCp -- Primary Mem V Mem copy */ if (md < 0) goto illins; pm [dmap(v2)] = pm [v1]; break; case 35: /* VmPmCp */ if (md < 0) goto illins; pm [v2] = pm[dmap(v1)]; break; case 36: /* Arm */ if (md < 0) goto illins; ar |= pm [dmap(v1)]; break; case 37: /* Disarm */ if (md < 0) goto illins; ar &= (-1-pm[dmap(v1)]); break; case 38: /* OS Call */ if (md > 0) goto illins; ie |= EBIT; /* set exception */ pm [sp+PSR_ECD] = a1; /* OS Call Number */ break; case 40: /* Floppy IO */ if (md < 0) goto illins; if (pm[LCL_FCP] < 0) { hlt = TRUE; break; } floppy_io (); break; case 41: /* Disk IO */ if (md < 0) goto illins; if (pm[LCL_DCP] < 0) { hlt = TRUE; break; } disk_io (); break; case 42: /* Print IO */ /* Advance one line and printf pm[v1] */ if (md < 0) goto illins; fprintf (printer,"\t%s\t%8x\n",LP_STR,pm[v1]); fflush(printer); break; case 43: /* Log */ if (md < 0) goto illins; log (v1, v2); break; /* Cases 44 and 45 not written yet */ case 44: /* TTY IN */ if (md < 0) goto illins; break; case 45: /* TTY Out */ if (md < 0) goto illins; break; /*********************************************/ case 48: /* Head Record */ if (moverec(v1,v2,pm[dmap(v1)])) pc++; break; case 49: /* Move Record */ if (moverec (v1, v2, xr)) pc++; break; case 50: /* Insert Record */ if (xr < 0) break; insrec (v1, pm[dmap(v2)], xr); pc++; break; case 51: /* Find Record */ while (((pm[dmap(v1)+1] & pm[dmap(v2)]) != gr) && (pm[dmap(v1)] > 0)) { v1 = pm[dmap(v1)]; } if ((pm[dmap(v1)+1] & pm[dmap(v2)]) == gr) { xr = v1; pc++; } break; case 53: /* Allocate */ if (allocate(v1,v2,gr)) pc++; break; case 54: /* DeAllocate */ if (deallocate(v1,v2,gr)) pc++; break; case 56: /* SP Load */ if (md < 0) goto illins; sp = pm [dmap(v1)]; break; case 57: /* Switch Process */ if (md < 0) goto illins; swcontxt (v1, v2); break; case 60: /* Send Message */ if (md < 0) goto illins; if (pm [LCL_MSF] > 0) send_mesg (); break; case 61: /* Receive Message */ if (md < 0) goto illins; if (pm[dmap(sp + PSR_MSQ)] > 0) recv_mesg (); else { /* reset M bit and switch to scheduler */ pc--; pm[dmap(sp + PSR_STW)] |= MBIT; swcontxt (pm[LCL_SCH], pc); } break; default: hlt = TRUE; /* Unused Op */ break; } /* End Case */ goto realtm ; /* Ready for real time section */ /* Real Time Code */ realtm: pm [LCL_TOD]++; /* Increment Time of Day */ pm [LCL_ALM]++; /* Increment Alarm */ if (pm [LCL_ALM] == 0) ie |= ABIT; /* Set the Alarm */ if (sp > 0) pm [sp+PSR_CPT]++; /* Increment CPU time */ if (fbsyrd) /* Floppy busy? Get 2 wrds */ { /* Read two words */ /* is it pointing to the correct place? */ if (fread (&pm[ftx], WD_B, 2, floppy) != 2) { fbsyrd = 0; pc --; } else { ftx += 2; if (ftx == ftul) { fbsyrd = 0; ie |= FBIT; md &= ~(1<<FBIT); } } } if (dbsyrd) /* Disk Busy Reading ? Get 2 Words */ { recv (dmasock, &pm[dtx], 2*WD_B, 0); dtx += 2; if (dtx == dtul) { dbsyrd = 0; ie |= DBIT; md &= ~(1<<DBIT); } } else if (dbsywr) /* Disk Writing (and not reading) Send 2 words */ { write (dmasock, &pm[dtx], 2*WD_B); dtx += 2; if (dtx == dtul) { dbsywr = 0; ie |= DBIT; md &= ~(1<<DBIT); } } /* Interrupt Handling */ if (ie != 0 && ar < 0) { int intr; int md_sign; int md_val; /* If something else running and this is not a greater one ignore for now */ if ((extract (md,0,WD_L-1) != 0) && (md <= ie)) return; /* Go away */ /* Get sign bit */ md_sign = (extract (md,(WD_L-1),1)) << (WD_L-1) ; /* Get the rightmost interrupt and make sure it can execute */ for (i=0; i< LEV_N; i++) { if ( (intr = (ffs (ie)-1)) != -1) /* Find the int */ if (extract (ar,intr,1)) /* Is it armed? */ { if (sp > 0) /* Set the "return to" value to SP */ pm [LCL_ITV + (2*intr) +1] = sp; else { hlt = TRUE ; break ; } ie &= ~(1<<intr); /* Clear the int */ swcontxt (pm[LCL_ITV+(2*intr)], pc); /* Switch to it */ md = (1 << intr); /* Set mode register */ /* md = ((1<<intr) | md_sign); /* Set mode register */ break; } } } return; /* Illegal instruction */ illins: ecd = INSTFLT; printf ("\n\nIll Ins ECD : %x\n\n", ecd); goto except; /* Exception */ except: ie |= EBIT; printf ("\nException Handler ECD : %x\n", ecd); if (sp > 0) pm [sp+PSR_ECD] = ecd; else hlt = TRUE; return; }