1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-21 00:25:37 +00:00

[fsp] fsp protocol support non-forking version based on fsplib

Maybe under DOS it makes sense.
It works worse than with fsplib. You can only download one file at a time.
This commit is contained in:
Witold Filipczyk 2023-07-07 21:49:39 +02:00
parent 9b3cbca0fb
commit 0e482b02da
12 changed files with 1677 additions and 6 deletions

View File

@ -85,6 +85,9 @@
/* Define if you want: FSP protocol support */
#mesondefine CONFIG_FSP
/* Define if you want: FSP protocol support without fork calls */
#mesondefine CONFIG_FSP2
/* Define if you want: FTP protocol support */
#mesondefine CONFIG_FTP

View File

@ -41,6 +41,7 @@ conf_data.set('CONFIG_CGI', get_option('cgi'))
conf_data.set('CONFIG_DGI', get_option('dgi'))
conf_data.set('CONFIG_FINGER', get_option('finger'))
conf_data.set('CONFIG_FSP', get_option('fsp'))
conf_data.set('CONFIG_FSP2', get_option('fsp2'))
conf_data.set('CONFIG_FTP', get_option('ftp'))
conf_data.set('CONFIG_GOPHER', get_option('gopher'))
conf_data.set('CONFIG_NNTP', get_option('nntp'))

View File

@ -15,6 +15,7 @@ option('uri-rewrite', type: 'boolean', value: true, description: 'URI rewrite su
option('cgi', type: 'boolean', value: false, description: 'local CGI support')
option('finger', type: 'boolean', value: false, description: 'finger protocol support')
option('fsp', type: 'boolean', value: false, description: 'FSP protocol support')
option('fsp2', type: 'boolean', value: false, description: 'FSP protocol support without fsplib and fork calls')
option('ftp', type: 'boolean', value: true, description: 'ftp protocol support')
option('gopher', type: 'boolean', value: false, description: 'gopher protocol support')
option('nntp', type: 'boolean', value: false, description: 'nntp protocol support')

View File

@ -62,7 +62,6 @@ struct module fsp_protocol_module = struct_module(
/* done: */ NULL
);
/* Because functions of fsplib block waiting for a response from the
* server, and ELinks wants non-blocking operations so that other
* connections and the user interface keep working, this FSP protocol

View File

@ -1,4 +1,3 @@
#ifndef EL__PROTOCOL_FSP_FSP_H
#define EL__PROTOCOL_FSP_FSP_H
@ -11,7 +10,7 @@ extern "C" {
extern struct module fsp_protocol_module;
#ifdef CONFIG_FSP
#if defined(CONFIG_FSP) || defined(CONFIG_FSP2)
extern protocol_handler_T fsp_protocol_handler;
#else
#define fsp_protocol_handler NULL

1179
src/protocol/fsp/fsp2.c Normal file

File diff suppressed because it is too large Load Diff

152
src/protocol/fsp/fsplib.h Normal file
View File

@ -0,0 +1,152 @@
#ifndef EL__PROTOCOL_FSP_FSPLIB_H
#define EL__PROTOCOL_FSP_FSPLIB_H
#include <time.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stddef.h>
/* The FSP v2 protocol support library - public interface */
/*
This file is part of fsplib - FSP protocol stack implemented in C
language. See http://fsp.sourceforge.net for more information.
Copyright (c) 2003-2005 by Radim HSN Kolar (hsn@sendmail.cz)
You may copy or modify this file in any manner you wish, provided
that this notice is always included, and that you hold the author
harmless for any loss or damage resulting from the installation or
use of this software.
This is a free software. Be creative.
Let me know of any bugs and suggestions.
*/
/* definition of FSP protocol v2 commands */
#define FSP_CC_VERSION 0x10 /* return server's version string. */
#define FSP_CC_INFO 0x11 /* return server's extended info block */
#define FSP_CC_ERR 0x40 /* error response from server. */
#define FSP_CC_GET_DIR 0x41 /* get a directory listing. */
#define FSP_CC_GET_FILE 0x42 /* get a file. */
#define FSP_CC_UP_LOAD 0x43 /* open a file for writing. */
#define FSP_CC_INSTALL 0x44 /* close a file opened for writing. */
#define FSP_CC_DEL_FILE 0x45 /* delete a file. */
#define FSP_CC_DEL_DIR 0x46 /* delete a directory. */
#define FSP_CC_GET_PRO 0x47 /* get directory protection. */
#define FSP_CC_SET_PRO 0x48 /* set directory protection. */
#define FSP_CC_MAKE_DIR 0x49 /* create a directory. */
#define FSP_CC_BYE 0x4A /* finish a session. */
#define FSP_CC_GRAB_FILE 0x4B /* atomic get+delete a file. */
#define FSP_CC_GRAB_DONE 0x4C /* atomic get+delete a file done. */
#define FSP_CC_STAT 0x4D /* get information about file. */
#define FSP_CC_RENAME 0x4E /* rename file or directory. */
#define FSP_CC_CH_PASSWD 0x4F /* change password */
#define FSP_CC_LIMIT 0x80 /* # > 0x7f for future cntrl blk ext. */
#define FSP_CC_TEST 0x81 /* reserved for testing */
/* FSP v2 packet size */
#define FSP_HSIZE 12 /* 12 bytes for v2 header */
#define FSP_SPACE 1024 /* maximum payload. */
#define FSP_MAXPACKET FSP_HSIZE+FSP_SPACE /* maximum packet size. */
/* byte offsets of fields in the FSP v2 header */
#define FSP_OFFSET_CMD 0
#define FSP_OFFSET_SUM 1
#define FSP_OFFSET_KEY 2
#define FSP_OFFSET_SEQ 4
#define FSP_OFFSET_LEN 6
#define FSP_OFFSET_POS 8
/* types of directory entry */
#define FSP_RDTYPE_END 0x00
#define FSP_RDTYPE_FILE 0x01
#define FSP_RDTYPE_DIR 0x02
#define FSP_RDTYPE_LINK 0x03
#define FSP_RDTYPE_SKIP 0x2A
/* definition of directory bitfield for directory information */
/* directory information is just going to be a bitfield encoding
* of which protection bits are set/unset
*/
#define FSP_PRO_BYTES 1 /* currently only 8 bits or less of info */
#define FSP_DIR_OWNER 0x01 /* does caller own directory */
#define FSP_DIR_DEL 0x02 /* can files be deleted from this dir */
#define FSP_DIR_ADD 0x04 /* can files be added to this dir */
#define FSP_DIR_MKDIR 0x08 /* can new subdirectories be created */
#define FSP_DIR_GET 0x10 /* are files readable by non-owners? */
#define FSP_DIR_README 0x20 /* does this dir contain an readme file? */
#define FSP_DIR_LIST 0x40 /* public can list directory */
#define FSP_DIR_RENAME 0x80 /* can files be renamed in this dir */
/* decoded FSP packet */
typedef struct FSP_PKT {
unsigned char cmd; /* message code. */
unsigned char sum; /* message checksum. */
unsigned short key; /* message key. */
unsigned short seq; /* message sequence number. */
unsigned short len; /* number of bytes in buf 1. */
unsigned int pos; /* location in the file. */ unsigned short xlen; /* number of bytes in buf 2 */
unsigned char buf[FSP_SPACE]; /* packet payload */
} FSP_PKT;
/* FSP host:port */
typedef struct FSP_SESSION {
void * lock; /* key locking */
unsigned int timeout; /* send timeout 1/1000s*/
unsigned int maxdelay; /* maximum recv. delay */
unsigned short seq; /* sequence number */
unsigned int dupes; /* total pkt. dupes */
unsigned int resends; /* total pkt. sends */
unsigned int trips; /* total pkt trips */
unsigned long rtts; /* cumul. rtt */
unsigned int last_rtt; /* last rtt */
unsigned int last_delay; /* last delay time */
unsigned int last_dupes; /* last dupes */
unsigned int last_resends;/* last resends */
int fd; /* i/o descriptor */
char *password; /* host acccess password */
} FSP_SESSION;
/* fsp directory handle */
typedef struct FSP_DIR {
char *dirname; /* directory name */
short inuse; /* in use counter */
int dirpos; /* current directory pos. */
unsigned short blocksize; /* size of directory block */
unsigned char *data; /* raw directory data */
unsigned int datasize; /* size of raw dir. data */
} FSP_DIR;
/* fsp directory entry */
typedef struct FSP_RDENTRY {
char name[255 + 1]; /* entry name */
unsigned short namlen; /* length */
unsigned char type; /* field type */
unsigned short reclen; /* directory record length */
unsigned int size;
unsigned int lastmod;
} FSP_RDENTRY;
/* fsp file handle */
typedef struct FSP_FILE {
FSP_PKT in,out; /* io packets */
FSP_SESSION *s; /* master session */
char *name; /* filename for upload */
unsigned char writing; /* opened for writing */
unsigned char eof; /* EOF reached? */
unsigned char err; /* i/o error? */
int bufpos; /* position in buffer */
unsigned int pos; /* position of next packet */
} FSP_FILE;
typedef union dirent_workaround {
struct dirent dirent;
char fill[offsetof (struct dirent, d_name) + MAXNAMLEN + 1];
} dirent_workaround;
#endif

284
src/protocol/fsp/lock.c Normal file
View File

@ -0,0 +1,284 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdio.h>
#include "protocol/fsp/lock.h"
/* ************ Locking functions ***************** */
#ifndef FSP_NOLOCKING
static char code_str[] =
"0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static void
make_key_string(FSP_LOCK *lock, unsigned long server_addr, unsigned long server_port)
{
unsigned long v1, v2;
char *p;
strcpy(lock->key_string, FSP_KEY_PREFIX);
for (p = lock->key_string; *p; p++);
v1 = server_addr;
v2 = server_port;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
v1 = v1 | (v2 << (32-3*6));
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p++ = code_str[v1 & 0x3f]; v1 >>= 6;
*p = 0;
}
#endif
/********************************************************************/
/******* For those systems that has SysV shared memory + semop ******/
/********************************************************************/
#ifdef FSP_USE_SHAREMEM_AND_SEMOP
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef _SEM_SEMUN_UNDEFINED
union semun
{
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
#endif
unsigned short
client_get_key(FSP_LOCK *lock)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
if (semop(lock->lock_sem,&sem,1) == -1) {
perror("semop lock");
}
return (*lock->share_key);
}
void
client_set_key(FSP_LOCK *lock,unsigned short key)
{
struct sembuf sem;
sem.sem_num = 0;
sem.sem_op = 1;
sem.sem_flg = SEM_UNDO;
*lock->share_key = key;
if (semop(lock->lock_sem,&sem,1) == -1) {
perror("semop unlock");
}
}
int
client_init_key(FSP_LOCK *lock, unsigned long server_addr, unsigned short server_port)
{
mode_t omask;
key_t lock_key;
int fd;
union semun su;
struct sembuf sem;
make_key_string(lock, server_addr, server_port);
omask = umask(0);
fd = open(lock->key_string, O_RDWR|O_CREAT, 0666);
umask(omask);
close(fd);
if ((lock_key = ftok(lock->key_string, 238)) == -1) {
perror("ftok");
return -1;
}
if ((lock->lock_shm = shmget(lock_key, 2 * sizeof(unsigned int), IPC_CREAT|0666)) == -1) {
perror("shmget");
return -1;
}
if (!(lock->share_key = (unsigned int *)shmat(lock->lock_shm, NULL, 0))) {
perror("shmat");
return -1;
}
if ((lock->lock_sem = semget(lock_key, 0, 0)) == -1) {
/* create a new semaphore and init it */
if ((lock->lock_sem = semget(lock_key, 2, IPC_CREAT|0666)) == -1) {
perror("semget");
return -1;
}
/* we need to init this semaphore */
su.val = 1;
if (semctl(lock->lock_sem, 0, SETVAL,su) == -1) {
perror("semctl setval");
return -1;
}
}
/* increase in use counter */
sem.sem_num = 1;
sem.sem_op = 1;
sem.sem_flg = SEM_UNDO;
if (semop(lock->lock_sem, &sem, 1) == -1) {
perror("semop incuse");
}
return 0;
}
void
client_destroy_key(FSP_LOCK *lock)
{
int rc;
struct sembuf sem;
if (shmdt(lock->share_key) < 0) {
perror("shmdt");
return;
}
/* check if we are only one process holding lock */
rc = semctl(lock->lock_sem, 1, GETVAL);
if (rc == 1) {
/* safe to destroy */
if (
(semctl(lock->lock_sem,0,IPC_RMID) < 0) ||
(shmctl(lock->lock_shm,IPC_RMID,NULL) < 0) ||
(unlink(lock->key_string) < 0) ) {
rc = 0;/* ignore cleanup errors */
}
} else if (rc > 1) {
/* we need to decrease sem. */
sem.sem_num = 1;
sem.sem_op = -1;
sem.sem_flg = SEM_UNDO;
if (semop(lock->lock_sem,&sem,1) == -1) {
perror("semop decuse");
}
}
}
#endif
/********************************************************************/
/******* For those who do not want to use locking *******************/
/********************************************************************/
#ifdef FSP_NOLOCKING
unsigned short
client_get_key(FSP_LOCK *lock)
{
return lock->share_key;
}
void
client_set_key(FSP_LOCK *lock,unsigned short key)
{
lock->share_key = key;
}
int
client_init_key(FSP_LOCK *lock, unsigned long server_addr, unsigned short server_port)
{
return 0;
}
void
client_destroy_key(FSP_LOCK *lock)
{
return;
}
#endif
/********************************************************************/
/******* For those systems that has lockf function call *************/
/********************************************************************/
#ifdef FSP_USE_LOCKF
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
unsigned short
client_get_key(FSP_LOCK *lock)
{
unsigned int okey;
if (lockf(lock->lock_fd, F_LOCK, sizeof(okey)) < 0) {
perror("lockf");
}
if (read(lock->lock_fd, &okey, sizeof(okey)) < 0) {
perror("readlk");
}
if (lseek(lock->lock_fd, 0L, 0) < 0) {
perror("seek");
}
return(okey);
}
void
client_set_key(FSP_LOCK *lock,unsigned short nkey)
{
unsigned int key;
key = nkey;
if (write(lock->lock_fd, &key, sizeof(key)) < 0) {
perror("write");
}
if (lseek(lock->lock_fd, 0L, 0) < 0) {
perror("seek");
}
if (lockf(lock->lock_fd, F_ULOCK, sizeof(key)) < 0) {
perror("unlockf");
}
}
int
client_init_key(FSP_LOCK *lock, unsigned long server_addr, unsigned short server_port)
{
mode_t omask;
make_key_string(lock,server_addr, server_port);
omask = umask(0);
lock->lock_fd = open(lock->key_string, O_RDWR | O_CREAT, 0666);
(void)umask(omask);
if (lock->lock_fd < 0) {
return -1;
} else {
return 0;
}
}
void
client_destroy_key(FSP_LOCK *lock)
{
(void)close(lock->lock_fd);
}
#endif

47
src/protocol/fsp/lock.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef EL__PROTOCOL_FSP_LOCK_H
#define EL__PROTOCOL_FSP_LOCK_H 1
#define FSP_NOLOCKING 1
#ifndef FSP_NOLOCKING
/* define locking prefix if needed */
# ifndef FSP_KEY_PREFIX
# define FSP_KEY_PREFIX "/tmp/.FSPL"
# endif
#endif
#ifdef FSP_USE_SHAREMEM_AND_SEMOP
typedef struct FSP_LOCK {
unsigned int *share_key;
int lock_shm;
int lock_sem;
char key_string[sizeof(FSP_KEY_PREFIX)+32];
} FSP_LOCK;
#elif defined(FSP_NOLOCKING)
typedef struct FSP_LOCK {
unsigned short share_key;
} FSP_LOCK;
#elif defined(FSP_USE_LOCKF)
typedef struct FSP_LOCK {
int lock_fd;
char key_string[sizeof(FSP_KEY_PREFIX)+32];
} FSP_LOCK;
#else
#error "No locking type specified"
#endif
/* prototypes */
unsigned short client_get_key (FSP_LOCK *lock);
void client_set_key (FSP_LOCK *lock,unsigned short key);
int client_init_key (FSP_LOCK *lock,
unsigned long server_addr,
unsigned short server_port);
void client_destroy_key(FSP_LOCK *lock);
#endif

View File

@ -1 +1,7 @@
srcs += files('fsp.c')
if conf_data.get('CONFIG_FSP2')
srcs += files('fsp2.c', 'lock.c')
endif
if conf_data.get('CONFIG_FSP')
srcs += files('fsp.c')
endif

View File

@ -7,7 +7,7 @@ endif
if conf_data.get('CONFIG_FINGER')
subdir('finger')
endif
if conf_data.get('CONFIG_FSP')
if conf_data.get('CONFIG_FSP') or conf_data.get('CONFIG_FSP2')
subdir('fsp')
endif
if conf_data.get('CONFIG_FTP')

View File

@ -313,7 +313,7 @@ static struct module *protocol_submodules[] = {
#ifdef CONFIG_FINGER
&finger_protocol_module,
#endif
#ifdef CONFIG_FSP
#if defined(CONFIG_FSP) || defined(CONFIG_FSP2)
&fsp_protocol_module,
#endif
#ifdef CONFIG_FTP