📄 cmds.h
字号:
#ifndef _NAP_CMDS_H#define _NAP_CMDS_H/* Copyright (c) 2000 Kevin Sullivan <nite@gis.net> * * Please refer to the COPYRIGHT file for more information. */#include <sys/time.h>#include <netinet/in.h>#include "scheck.h"struct out_nap_cmd_s { const char *nm; unsigned char a; int (*func)(int, char *, char **, int, WINDOW *); const char *help;};typedef struct out_nap_cmd_s out_nap_cmd_t;struct user_s { char *nm, *addr; unsigned char conn; unsigned int scount; unsigned char flag; struct user_s *next;};typedef struct user_s user_t;struct hotlist_s { char *nm; /* allocated */ int conn; int on; struct hotlist_s *next;};typedef struct hotlist_s hotlist_t;/* this is the type of channels as well as queries. A query is a (virtual) connection to a single user */struct chans_s { char *nm; /* name of channel/query - case insensitive */ char *topic; user_t *users; unsigned char q; /* 0: napster channel, 1: query, 2: irc (?) */ unsigned char flag; /* ? */ int l; /* ? */ char *key; /* ? */ unsigned char p; /* ? */ struct chans_s *next;}; typedef struct chans_s chans_t;struct scount_s { unsigned long libraries, songs, gigs;};typedef struct scount_s scount_t;struct stringlist_s{ char *s; struct stringlist_s *next;};typedef struct stringlist_s stringlist_t;/* ---------------------------------------------------------------------- *//* the data structure for search result items. Note: the convention is that the items of the search result list are numbered sequentially, starting from *1*. However, the list macros start numbering from *0*. Thus, careful when looking for item number n. */struct ssearch_s { char *song; /* title with pathname componentes stripped */ char *rfn; /* title as sent by server */ char *nick; /* nickname of remote user */ int conn; /* connection speed of remote client */ size_t sz; /* total size */ int brate; /* bitrate (e.g. 128) */ int freq; /* sample frequency (e.g. 44100) */ int time; /* length, in seconds */ unsigned long nip; /* ip address of remote client, in network byte order (formerly this field was called ip and was in non-host byte order) */ int ping; /* ping time (in milliseconds). -3 or -2 if none requested, -1 if infinity */ struct ssearch_s *next; /* next item in list */ struct ssearch_s *next1; /* only used for sorting; need not initialize */};typedef struct ssearch_s ssearch_t;/* ---------------------------------------------------------------------- *//* the data structure for incomplete-tags: this is a special tag appended to an incomplete file, which facilitates resumes. The tag has an ASCII form and an internal form. Note the "lfn" and "next" fields are not represented in the ASCII tag. */struct itag_s{ int n; /* number of available hashes (up to 3) */ char *hash[3]; /* array of hashes */ char *lfn; /* path to the incomplete file */ char *fn; /* original filename */ struct itag_s *next; /* linked lists */};typedef struct itag_s itag_t;/* ---------------------------------------------------------------------- *//* The task lists are two of the three "backbone" data structures of nap (the remaining one is the connection list, type sock_t, see scheck.h). A "task" is an upload or a download. Tasks are kept in two global linked lists, "up" and "down". The following is my attempt at a specification of what these data structures represent, and how they are updated in reaction to user events, server events, and timeouts. A task can be in several different states. For download tasks, these are: QUEUED: requested by the user, but not yet requested from server. RQUEUED: "remotely queued". Try to re-request later. RRQUEUED: "remotely queued" and requested. REQUESTED: requested from server, but not yet acknowledged by server. WAITING: waiting for remote client to contact us. CONNECTING: contacted remote client and waiting for a response. IN PROGRESS: reading file from the remote client. COMPLETE: file successfully received. INCOMPLETE: we were disconnected after receiving a partial file. FAILED: error before receiving file (e.g. it did not exist) TIMED_OUT: waited too long for server or remote client. For upload tasks, the possible states are very similar: WAITING: waiting for remote client to contact us. CONNECTING: contacted remote client and waiting for a response. IN PROGRESS: sending file to the remote client. COMPLETE: file successfully sent. INCOMPLETE: disconnected after sending partial file. FAILED: error before sending file (e.g. it did not exist) TIMED_OUT: waited too long for server or remote client. Note that there are no QUEUED, RQUEUED, RRQUEUED or REQUESTED states for uploads, since uploads are always initiated by the server (we do not queue uploads). Not all of the above states need to be explicitly represented in the data structures. For instance, one may choose to implement COMPLETE, INCOMPLETE, FAILED, and TIMED_OUT simply by deleting the task. On the other hand, a clever client might want to try to something smart with an INCOMPLETE, for instance, try to resume it. Much of the napster protocol has to do with what messages to expect and send in each state, and how to change states. The following model explains how to react to each condition in each state. This could be represented as a flow graph, but that's difficult to do in ASCII. ------------------------------------------------------------------- 1. Downloads. [no state]: user download request (if limit exceeded) -> create task -> QUEUED [no state]: user download request (if limit ok, and there is not already an R*QUEUED item by this nick) -> create task -> send 203 (download request) to server -> REQUESTED [no state]: user download request (if limit ok, and there is already an R*QUEUED item by this nick) -> create task -> RQUEUED (with timer set to retry this item). QUEUED: (when a slot becomes available) -> send 203 (download request) to server -> REQUESTED RQUEUED: (when timer due and slot available) -> send 203 (download request) to server -> RRQUEUED REQUESTED or RRQUEUED: receive 206 (get error) from server -> FAILED REQUESTED or RRQUEUED: receive 609 (accept failure) from server -> FAILED REQUESTED or RRQUEUED: receive 620 (queue limit) from server (if remote upload limit >= 1) -> RQUEUED (with timer set to retry this item). REQUESTED or RRQUEUED: receive 620 (queue limit) from server (if remote upload limit <= 0) -> FAILED REQUESTED or RRQUEUED: receive 204 (download ack) from server (if remote party is firewalled) -> send 500 (alt download request) to server -> WAITING REQUESTED or RRQUEUED: receive 204 (download ack) from server (if remote party is not firewalled) -> contact remote client -> CONNECTING REQUESTED: (timed out) -> resend 203 to server -> REQUESTED RRQUEUED: (timed out) -> resend 203 to server -> RRQUEUED WAITING: remote client connects to us (if negotiation fails) -> FAILED WAITING: remote client connects to us (if negotiation succeeds) -> send 218 (downloading) to sever -> IN PROGRESS WAITING: (timed out) -> TIMED_OUT CONNECTING: remote client responds (if negotiation fails) -> FAILED CONNECTING: remote client responds (if negotiation succeeds) -> send 218 (downloading) to sever -> IN PROGRESS CONNECTING: (timed out) -> TIMED_OUT IN PROGRESS: receive data -> IN PROGRESS IN PROGRESS: (transfer complete) -> send 219 (download complete) to server -> COMPLETE IN PROGRESS: (transfer interrupted) -> send 219 (download complete) to server -> INCOMPLETE FAILED or COMPLETE or INCOMPLETE or TIMED_OUT: -> purge/delete -> [no state] ------------------------------------------------------------------- 2. Uploads. [no state]: receive 607 (upload request) from server (if we don't have the file, or /tquit is currently in effect) -> send 608 (accept upload request) to server -> [no state] (Note: there is no "reject upload request" packet!) [no state]: receive 607 (upload request) from server (if upload limit exceeded) -> send 619 (queue limit) to server -> [no state] [no state]: receive 607 (upload request) from server (otherwise) -> create task -> send 608 (accept upload request) to server -> WAITING WAITING: remote client connects to us (if negotiation fails) -> FAILED WAITING: remote client connects to us (if negotiation succeeds) -> send 220 (uploading) to server and go to IN PROGRESS WAITING: receive 501 (alt download ack or "push request") from server -> contact remote client -> CONNECTING WAITING: (timed out) -> TIMED_OUT (Note: apparently, 501 is only sent after 607. But we may also choose to accept 501 in [no state] - are not currently doing so, however.) CONNECTING: remote client responds (if negotiation fails) -> FAILED (Note: there might be no harm in allowing an upload of a shared file even if it does not seem to have been initiated by the server, *provided* that we have space available. Usually this happens if a remote client sent an upload request, we received it, then we quit and restarted. The remote client will now try to connect to us, but we have erased our upload list!) CONNECTING: remote client responds (if negotiation succeeds) -> CONNECTING1 -> (continue negotiation) -> send 220 (uploading) to server -> IN PROGRESS CONNECTING: (timed out) -> TIMED_OUT IN PROGRESS: send data -> IN PROGRESS IN PROGRESS: (transfer complete) -> send 221 (upload complete) to server -> COMPLETE IN PROGRESS: (disconnected) -> send 221 (upload complete) to server -> INCOMPLETE FAILED, COMPLETE, INCOMPLETE, TIMEOUT: -> purge -> [no state] ------------------------------------------------------------------- Some states may split into even more sub-states, for instance, CONNECTING usually involves first sending a GET and then waiting one more time for the remote client's response. This is implemented by remaining in the same state, but updating the (sock_t) "func" entry.*/#define QUEUED 0#define RQUEUED 1#define IN_PROGRESS 2#define RRQUEUED 3#define REQUESTED 4#define WAITING 5#define CONNECTING 6#define CONNECTING1 7#define FAILED -1#define INCOMPLETE -2#define COMPLETE -3#define TIMED_OUT -4#define STOPPED(x) ((x)<0) /* FAILED, INCOMPLETE, COMPLETE, TIMED_OUT */#define ACTIVE(x) ((x)>=2) /* not STOPPED or QUEUED or RQUEUED */#define TIMED(x) ((x)>=3) /* RRQUEUED, REQUESTED, WAITING, CONNECTING(1) *//* note: in the following, if a certain field is marked "in state xxx", then this means the field's value is undefined in any other state. In particular, such fields need not be (and are not usually)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -