int isRCValid(int rc) { if (rc < 0) writeErr(" select() failed"); if (rc == 0) writeErr(" select() timed out. End program."); return rc; }
/* * something went wrong fetching data * produce fill bytes for what we've committed to produce */ void fetchBodyFill(ulong n) { while(n-- > 0) if(Bputc(&bout, ' ') < 0) writeErr(); }
int init() { clientCount = 0; int i = 0; for (; i < CLIENT_SIZE; i++) resetClient(&clients[i]); int listen_sd, on = 1; struct sockaddr_in addr; listen_sd = socket(AF_INET, SOCK_STREAM, 0); if (listen_sd < 0) { writeErr("socket() failed"); return -1; } int rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (char*) &on, sizeof(on)); if (rc < 0) { writeErr("setsockopt() failed"); close(listen_sd); return -1; } rc = ioctl(listen_sd, FIONBIO, (char *) &on); if (rc < 0) { writeErr("ioctl() failed"); close(listen_sd); return -1; } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY ); addr.sin_port = htons(SERVER_PORT); rc = bind(listen_sd, (struct sockaddr *) &addr, sizeof(addr)); if (rc < 0) { println("bind() failed"); close(listen_sd); return -1; } rc = listen(listen_sd, 5); if (rc < 0) { writeErr("listen() failed"); close(listen_sd); return -1; } return listen_sd; }
int do_send_size(char* line, int size, int sockfd) { int len = send(sockfd, line, size, 0); if (len != size) { writeErr("Error is send"); return -1; } return 0; }
int do_send(char* line, int sockfd) { int len = send(sockfd, line, strlen(line) + 1, 0); if (len != strlen(line) + 1) { writeErr("Error is send"); return -1; } return 0; }
int sendFile(int index, int num, char* line) { if (lock_id != -1) { println("This operation cannot be done"); do_send("Prob: server is busy", clients[num].fd); return 1; } char recv_buf[BUFFER_SIZE]; char completeName[BUFFER_SIZE] = ""; // "__shared__"; strcpy(completeName, MY_PATH); char fileName[BUFFER_SIZE]; index = nextToken(line, fileName, index); strcat(completeName, fileName); char pass[BUFFER_SIZE]; index = nextToken(line, pass, index); int q = 0; for (; q < clientCount; q++) { if (clients[q].fd != -1 && checkPassword(fileName, pass, q) != 0) { q = -1; break; } } if (q != -1) { println("This file '%s' doesn't exist or wrong password", fileName); do_send("Prob: File doesn't exist or wrong password", clients[num].fd); return -1; } int myFD = getROFile(completeName); if (myFD < 0) { println("I can't make this file %s", fileName); do_send("Problem:", clients[num].fd); return -1; } clients[num].myFD = myFD; lock_id = num; clients[num].startTime = time(NULL ); clients[num].send = 0; stat(completeName, &clients[num].info); writeErr("did you make it?"); do_send("Privilege granted", clients[num].fd); do_recieve(recv_buf, clients[num].fd); char tmpInt[BUFFER_SIZE] = ""; convertIntToString(clients[num].info.st_size, tmpInt); do_send(tmpInt, clients[num].fd); return 1; }
/* * rfc 2195 cram-md5 authentication */ char* cramauth(void) { AuthInfo *ai; Chalstate *cs; char *s, *t; int n; if((cs = auth_challenge("proto=cram role=server")) == nil) return "couldn't get cram challenge"; n = cs->nchal; s = binalloc(&parseBin, n * 2, 0); n = enc64(s, n * 2, (uint8_t*)cs->chal, n); Bprint(&bout, "+ "); Bwrite(&bout, s, n); Bprint(&bout, "\r\n"); if(Bflush(&bout) < 0) writeErr(); s = authresp(); if(s == nil) return "client cancelled authentication"; t = strchr(s, ' '); if(t == nil) bye("bad auth response"); *t++ = '\0'; strncpy(username, s, UserNameLen); username[UserNameLen-1] = '\0'; cs->user = username; cs->resp = t; cs->nresp = strlen(t); if((ai = auth_response(cs)) == nil) return "login failed"; auth_freechal(cs); setupuser(ai); return nil; }
int main(int argc, char *argv[]) { if (argc != 3) { writeErr("Error: Use ./server directory PORT"); return -1; } strcpy(MY_PATH, argv[1]); SERVER_PORT = atoi(argv[2]); int i, len, rc; int desc_ready, end_server = FALSE; int close_conn; char buffer[BUFFER_SIZE]; fd_set master_set, working_set; int max_sd, new_sd; int listen_sd = init(); if (listen_sd == -1) return -1; println("list"); FD_ZERO(&master_set); FD_SET(STDIN, &master_set); println("listening"); max_sd = listen_sd; FD_SET(listen_sd, &master_set); do { memcpy(&working_set, &master_set, sizeof(master_set)); // println("waiting for listen..."); rc = select(max_sd + 1, &working_set, NULL, NULL, NULL ); if (isRCValid(rc) <= 0) break; desc_ready = rc; for (i = 0; i <= max_sd && desc_ready > 0; ++i) { if (FD_ISSET(i, &working_set)) { desc_ready--; if (i == listen_sd) { print(" Listening socket is readable\n"); //DO_ACCEPT /**********************/ new_sd = accept(listen_sd, NULL, NULL ); if (new_sd < 0) { if (errno != EWOULDBLOCK) { writeErr(" accept() failed"); end_server = TRUE; } break; } print(" New incoming connection: %d\n", new_sd); rc = recv(new_sd, buffer, sizeof(buffer), 0); int q = 0; int flag = 0; for (; q < clientCount; q++) { if (clients[q].fd == -1) { flag = 1; clients[q].fd = new_sd; strcpy(clients[q].name, buffer); clients[q].id = q; println("cli#%d:%s", q, buffer); break; } } if (flag == 0) { q = clientCount; clients[q].fd = new_sd; strcpy(clients[q].name, buffer); clients[q].id = q; println("cli#%d:%s", q, buffer); clientCount++; } len = convertIntToString(q, buffer); rc = send(new_sd, buffer, len + 1, 0); println("It has been sent"); /**********************/ //END DO_ACCEPT FD_SET(new_sd, &master_set); if (new_sd > max_sd) max_sd = new_sd; } else if (i == STDIN) { memset(buffer, 0, BUFFER_SIZE); readLine(buffer); int index = 0; char next[BUFFER_SIZE]; memset(next, 0, BUFFER_SIZE); index = nextToken(buffer, next, index); if (strcmp("kick", next) == 0) { strcpy(buffer, buffer + 9); char tmpInt[BUFFER_SIZE] = ""; index = nextToken(buffer, tmpInt, 0); int q = atoi(tmpInt); int i = clients[q].fd; int j = 0; for (; j < clients[q].fileCount; j++) { char fileName[BUFFER_SIZE] = ""; strcpy(fileName, MY_PATH); strcat(fileName, clients[q].fileNames[j]); unlink(fileName); } resetClient(&clients[q]); close(i); FD_CLR(i, &master_set); if (i == max_sd) { while (FD_ISSET(max_sd, &master_set) == FALSE) max_sd -= 1; } } } else { // print(" Descriptor %d is readable\n", i); close_conn = FALSE; rc = recv(i, buffer, sizeof(buffer), 0); if (rc < 0) writeErr(" recv() failed"); if (rc == 0) { print(" Connection closed\n"); close_conn = TRUE; } len = rc; do_command(buffer, len, getNum(i)); if (close_conn) { int q = 0; int flag = 0; for (; q < clientCount; q++) { if (clients[q].fd == i) { int j = 0; for (; j < clients[q].fileCount; j++) { char fileName[BUFFER_SIZE] = ""; strcpy(fileName, MY_PATH); strcat(fileName, clients[q].fileNames[j]); unlink(fileName); } resetClient(&clients[q]); break; } } close(i); FD_CLR(i, &master_set); if (i == max_sd) { while (FD_ISSET(max_sd, &master_set) == FALSE) max_sd -= 1; } } } } } } while (end_server == FALSE); for (i = 0; i <= max_sd; ++i) { if (FD_ISSET(i, &master_set)) close(i); } }
/* * actually return the body pieces */ void fetchBody(Msg *m, Fetch *f) { Pair p; char *s, *t, *e, buf[BufSize + 2]; ulong n, start, stop, pos; int fd, nn; if(m == nil) { fetchBodyStr(f, "", 0); return; } switch(f->part) { case FPHeadFields: case FPHeadFieldsNot: n = m->head.size + 3; s = emalloc(n); n = selectFields(s, n, m->head.buf, f->hdrs, f->part == FPHeadFields); fetchBodyStr(f, s, n); free(s); return; case FPHead: fetchBodyStr(f, m->head.buf, m->head.size); return; case FPMime: fetchBodyStr(f, m->mime.buf, m->mime.size); return; case FPAll: fd = msgFile(m, "rawbody"); if(fd < 0) { msgDead(m); fetchBodyStr(f, "", 0); return; } p = fetchBodyPart(f, msgSize(m)); start = p.start; if(start < m->head.size) { stop = p.stop; if(stop > m->head.size) stop = m->head.size; Bwrite(&bout, &m->head.buf[start], stop - start); start = 0; stop = p.stop; if(stop <= m->head.size) { close(fd); return; } } else start -= m->head.size; stop = p.stop - m->head.size; break; case FPText: fd = msgFile(m, "rawbody"); if(fd < 0) { msgDead(m); fetchBodyStr(f, "", 0); return; } p = fetchBodyPart(f, m->size); start = p.start; stop = p.stop; break; default: fetchBodyStr(f, "", 0); return; } /* * read in each block, convert \n without \r to \r\n. * this means partial fetch requires fetching everything * through stop, since we don't know how many \r's will be added */ buf[0] = ' '; for(pos = 0; pos < stop; ) { n = BufSize; if(n > stop - pos) n = stop - pos; n = read(fd, &buf[1], n); if(n <= 0) { fetchBodyFill(stop - pos); break; } e = &buf[n + 1]; *e = '\0'; for(s = &buf[1]; s < e && pos < stop; s = t + 1) { t = memchr(s, '\n', e - s); if(t == nil) t = e; n = t - s; if(pos < start) { if(pos + n <= start) { s = t; pos += n; } else { s += start - pos; pos = start; } n = t - s; } nn = n; if(pos + nn > stop) nn = stop - pos; if(Bwrite(&bout, s, nn) != nn) writeErr(); pos += n; if(*t == '\n') { if(t[-1] != '\r') { if(pos >= start && pos < stop) Bputc(&bout, '\r'); pos++; } if(pos >= start && pos < stop) Bputc(&bout, '\n'); pos++; } } buf[0] = e[-1]; } close(fd); }