/************************************************************************/ /* */ /* ***** ***** */ /* ***** ***** */ /* ***** ***** */ /* ***** ***** */ /* *************** *************** */ /* ***************** ***************** */ /* *************** *************** */ /* ***** ***** TheNetNode */ /* ***** ***** Portable */ /* ***** ***** Network */ /* ***** ***** Software */ /* */ /* File src/pacserv.c (maintained by: ???) */ /* */ /* This file is part of "TheNetNode" - Software Package */ /* */ /* Copyright (C) 1998 - 2008 NORD> last_fid) last_fid = fid; if (fid < first_fid) first_fid = fid; if ((next = xfindnext(&fb)) != 0) break; } } if (first_fid == LONG_MAX) { first_fid = sys_time; last_fid = first_fid - 1L; } } /* die Ports initialisieren */ for (x = 0; x < L2PNUM; x++) { pacstate[x].busy = FALSE; pacstate[x].last = FALSE; pacstate[x].actfid = first_fid - 1; pacstate[x].fid200 = last_fid; pacsat_delay[x] = 0; } } /************************************************************************/ /* */ /* Garbage-Collection der Mailbox */ /* */ /************************************************************************/ static void garbage(void) { char name[MAXPATH]; while (first_fid + (LONG) pacsat_free <= last_fid) { make_name(first_fid++, name); xremove(name); } if (first_fid >= last_fid) filesystem_init(); } /************************************************************************/ /* */ /* PACSAT-Server initialisiern */ /* */ /************************************************************************/ void pacsat_init(void) { filesystem_init(); /*garbage();*/ } static UWORD calc_crc(char c, UWORD crc) { UWORD hi1, hi2; hi1 = ((crc >> 8) & 0xff); hi2 = ((crc & 0xff) << 8); return((crctab[hi1 ^ c] ^ hi2)); } /************************************************************************/ /* */ /* Dateigroesse ermitteln */ /* */ /************************************************************************/ static LONG fsize(char *name) { struct stat s; stat(name,&s); return(s.st_size); } /************************************************************************/ /* */ /* Das Temporaerfile "tempname" ins PACSAT-Fileformat uebernehmen. Alle */ /* PACSAT-Nachrichten werden im pacsatpath Verzeichnis gespeichert. Der */ /* Dateiname ist die 8-Stellige FileId (Hex, long) und die Endung .DAT */ /* */ /************************************************************************/ void new_file(char *tempname) { char e_name[MAXPATH]; char file1[MAXPATH], file2[MAXPATH]; char s[20], s2[20]; /* Neueingaenge aus dem Hintergrund, z.B. Netzwerk */ do { last_fid++; make_name(last_fid, file1); } while (!xaccess(file1, 0)); /* jetzt den Header hinzufuegen */ strcpy(file2, tempname); strcpy(e_name, pacsatpath); strcat(e_name, "PFHADD"); #ifndef __LINUX__ strcat(e_name, ".EXE"); #endif normfname(e_name); sprintf(s, "%lx", last_fid); callss2str(s2, calofs(UPLINK, userpo->uid)); if (spawnl(P_WAIT, e_name, e_name, file2, file1, s, s2, NULL) != 0) last_fid--; else garbage(); } /************************************************************************/ /* PacSat-Broadcast vorbereiten, Broadcast-Struktur fuellen */ /************************************************************************/ static WORD init_bcast(LONG fid, char port, PACTXDESC *tp) { char name[MAXPATH]; struct stat st; make_name(fid, name); tp->fid = fid; tp->port = port; tp->filesize = fsize(name); if ((tp->filehandle = fopen(name, "rb")) == NULL) return(FALSE); tp->pos = -1L; fstat(fileno(tp->filehandle), &st); tp->filetime = st.st_atime; tp->destcall = "QST \142"; tp->via = ""; return(TRUE); } /************************************************************************/ /* Ab der Adresse (!) Data Count Bytes in den Message-Buffer kopieren */ /************************************************************************/ static void add_frm(MBHEAD *mbp, char *x, WORD count) { while (count-- > 0) { mbp->l4time = calc_crc(*x, mbp->l4time); /* CRC updaten */ putchr(*(x++), mbp); } } #ifdef PAC_DEBUG UWORD gen_crc(UWORD crc, char data) { UWORD y; crc ^= ((UWORD)data) << 8; for (y = 0; y < 8; y++) if (crc & 0x8000) crc = (crc << 1) ^ 0x1021; else crc <<= 1; return(crc); } /* Debug-Funktion, CRC auf Richtigkeit ueberpruefen */ void ckcrc(MBHEAD *mbp) { UWORD crc = 0; rwndmb(mbp); /* Ueberprueft auf "traditioneller" Weise die CRC (ohne Tabelle) */ /* damit kann man auf Nummer sicher gehen beim senden ... */ /* nur fuer Tests! */ while (mbp->mbpc - mbp->mbgc > 2) crc = gen_crc(crc, getchr(mbp)); crc = gen_crc(crc, getchr(mbp)); /* 1. CRC Byte */ if (gen_crc(crc, getchr(mbp))) #ifdef SPEECH printf(speech_message(293)); #else printf("CRC Error\n"); #endif } #endif /***************************************************************************/ /* CRC fuer das Frame anhaengen (haben wir in l4time berechnet, s. add_frm */ /***************************************************************************/ static void add_crc(MBHEAD *mbp) { #ifdef __WIN32__ putchr((char)((mbp->l4time >> 8) & 0xff), mbp); putchr((char)(mbp->l4time & 0xff), mbp); #else putchr((mbp->l4time >> 8) & 0xff, mbp); putchr(mbp->l4time & 0xff, mbp); #endif /* WIN32 */ #ifdef PAC_DEBUG ckcrc(mbp); /* CRC ueberpruefen */ #endif } /************************************************************************/ /* Ein Frame broadcasten */ /************************************************************************/ static BOOLEAN send_frame(PACTXDESC *tp) { char flags = 0x00; /* Flag: Offset im Header enthalten */ char type = 0x00; char data_buf[blocksize+1], *cp; WORD data_size; WORD ret = TRUE; ULONG offset = 0L; MBHEAD *mbp; mbp = (MBHEAD *) allocb(ALLOC_MBHEAD); mbp->l4time = 0; /* Benutzen wir fuer die CRC */ if (tp->pos == -1L) { /* den PACSAT-Directory-Entry broadcasten */ /* ACHTUNG ! PFH groesser dir_blocksize muessten in 2 Durchgaengen ge- */ flags |= PF_E; /* broadcastet werden, das ist hier nicht vorgesehen */ tp->pos = 0L; /* beim naechsten mal das File selber broadcasten */ if (tp->fid == last_fid) flags |= PF_N; /* neuster Eintrag ? */ /* den Body-Offset bestimmen */ if (tp->filehandle != NULL) { fseek(tp->filehandle, 0L, SEEK_SET); fread(data_buf, blocksize, 1, tp->filehandle); for (cp = data_buf + 2; (cp < data_buf+blocksize) && (cp[2]); cp += cp[2] + 3); data_size = cp - data_buf; } else return(FALSE); /* jetzt den Directory Header aufbauen */ add_frm(mbp, &flags, 1); add_frm(mbp, (char *) &tp->fid, 4); add_frm(mbp, (char *) &offset, 4); add_frm(mbp, (char *) &tp->filetime, 4); /* t_old */ add_frm(mbp, (char *) &tp->filetime, 4); /* t_new */ if (data_size > 254 - mbp->mbpc) data_size = 254 - mbp->mbpc; add_frm(mbp, data_buf, data_size); add_crc(mbp); /* CRC an die Daten anhaengen */ rwndmb(mbp); /* Frame als UI-Frame senden */ mbp->l2fflg = 0xBD; /* PID 0xBD */ #ifdef __WIN32__ sdui(tp->via, tp->destcall, myid, (char)tp->port, mbp); #else sdui(tp->via, tp->destcall, myid, tp->port, mbp); #endif /* WIN32 */ dealmb(mbp); /* Wegwerfen, sdui kopiert selbstaendig um */ return(TRUE); } else flags = PF_O; /* PACSAT-Header aufbauen */ add_frm(mbp, &flags, 1); add_frm(mbp, (char *) &tp->fid, 4); add_frm(mbp, (char *) &type, 1); add_frm(mbp, (char *) &tp->pos, 3); if ((LONG) blocksize >= /* wenn maximaler Dateninhalt */ (tp->filesize - tp->pos) ) /* nicht gebraucht wird */ { data_size = (WORD) (tp->filesize - tp->pos); /* nur noch den Rest senden */ ret = FALSE; } else data_size = blocksize; #ifdef PAC_DEBUG printf("QST: msg=%lx offset=%lu, len=%d\n",tp->fid, tp->pos, data_size); #endif if (tp->filehandle != NULL) { fseek(tp->filehandle, tp->pos, 0); fread(data_buf, data_size, 1, tp->filehandle); /* Info lesen */ add_frm(mbp, data_buf, data_size); /* Daten kopieren */ tp->pos += (LONG) data_size; /* Offset erhoehen */ if (tp->pos >= tp->filesize) { fclose(tp->filehandle);/* fertig -> Datei zu */ } } else return(FALSE); /* es gibt nix mehr zu lesen ... */ add_crc(mbp); /* CRC an die Daten anhaengen */ rwndmb(mbp); /* Frame als UI-Frame senden */ mbp->l2fflg = 0xBB; /* PID 0xBB */ #ifdef __WIN32__ sdui(tp->via, tp->destcall, myid, (char)tp->port, mbp); #else sdui(tp->via, tp->destcall, myid, tp->port, mbp); #endif /* WIN32 */ dealmb(mbp); /* Wegwerfen, sdui kopiert selbstaendig um */ return(ret); } /************************************************************************/ /* eine Broadcastrunde auf einem bestimmen Port durchfuehren. */ /************************************************************************/ static BOOLEAN send_bcast2(WORD port) { WORD x; /* Falls die Datei nicht existiert */ if (pacstate[port].now.filehandle == NULL) return(FALSE); /* senden bis nix mehr da ist oder maximale Frame-Anzahl erreicht */ for (x = 0; x < pacsat_frames; x++) if (!send_frame(&pacstate[port].now)) return(FALSE); return(TRUE); } /************************************************************************/ /* Broadcast-Steuerung */ /* */ /* Die Routine sendet alle Files zwischen first_fd und last_fid. */ /* Das aktuell gesendete File wird in actfid gespeichert. */ /* Sind mehr als 200 Files vorhanden, wird last auf TRUE gesetzt */ /* Wenn LAST=TRUE ist, dann wird bei jedem zweiten Durchgang ein File */ /* aus den letzten 200 empfangenen Files gesendet. */ /* */ /* Bsp: */ /* Files 1-350 sind vorhanden. es wird gesendet: */ /* 001-350-002-349-003-348-004-347- ... */ /* 199-150-200-350-201-349- ... */ /* im Bsp. wird nicht beruecksichtigt, dass evtl neue Files einlaufen. */ /* */ /************************************************************************/ static void send_bcast(WORD port) { PACSTATEDESC *ps = &pacstate[port]; /* wenn noch im Transfer dann senden */ if (ps->busy) ps->busy = send_bcast2(port); /* wenn nichts mehr zu senden dann neuen Transfer beginnen */ if (!ps->busy) { if (ps->last) /* Wenn eine zwischenschieben */ { ps->fid200--; /* wieder mit der letzten anfangen */ if (ps->fid200 < (last_fid - 200)) ps->fid200 = last_fid; /* sicherheitshalber */ if (ps->fid200 < first_fid) ps->fid200 = last_fid; #ifdef __WIN32__ init_bcast(ps->fid200, (char)port, &ps->now); #else init_bcast(ps->fid200, port, &ps->now); #endif /* WIN32 */ ps->last = FALSE; } else { ps->actfid++; if (ps->actfid > last_fid) ps->actfid = first_fid; #ifdef __WIN32__ init_bcast(ps->actfid, (char)port, &ps->now); #else init_bcast(ps->actfid, port, &ps->now); #endif /* WIN32 */ if (last_fid - first_fid > 200) ps->last = TRUE; } ps->busy = TRUE; } } /****************************************************************************/ /* Broadcast Service, wird staendig in MAIN aufgerufen. Gesendet wird wenn */ /* der Sender nicht mehr beschaeftigt ist und mindestens der Verzoegerungs- */ /* Timer abgelaufen ist (fuer Einstiege die nebenher Broadcasten). */ /****************************************************************************/ void pacsrv(void) { #ifdef __WIN32__ ULONG zeit; #else UWORD zeit; #endif /* WIN32 */ static ULONG lasttic = 0; WORD x; if (last_fid < first_fid) return; zeit = tic10 - lasttic; lasttic = tic10; for (x = 0; x < L2PNUM; x++) if (pacsat_enabled[x]) if (!iscd(x)) { if (pacsat_delay[x] <= zeit) { send_bcast(x); pacsat_delay[x] = pacsat_timer; /* Timer wieder aufziehen */ } else #ifdef __WIN32__ pacsat_delay[x] -= (UWORD)zeit; #else pacsat_delay[x] -= zeit; #endif /* WIN32 */ } } #endif /* PACSAT */ /* End of src/pacserv.c */