Blob
- Date:
- Message:
- import gotwebd thread fcgi response to client for rendering in browser as data is returned fix potential problem with a stuck loop if the client is hammering the server with random clicks and stop/restarts render our index! WOOHOO! small var refactoring. fcgi.c to handle all clean-up, various error clean-up remove output used to trace down got bug temporarily stop overloading a socket, but a better solution needs to be found return on fcgi_gen_response, so we can track if a client is writable or not this stops page creation when the client is unavailable remove old comments enable profile building, although, i don't think this works thoroughly in a priv/proc daemon catch more errors correctly count repos remove temp logger we don't need to start our responder thread so early. move it to fcgi.c and start when we start processing html kill the unneeded thread, stop queueing responses, and just write to clients immediately clean up some memory leaks and dead stores rework querystring so an error can be displayed instead of showing the index on querystring error get framework in place for the rest of the content add server struct to response struct bo last commit get back a usable gotweb. not sure what i was thinking yesterday properly move our structs around this time remember index page for sitelink, fix leak unused var is annoying, so stop it for now. don't forget to change this! style briefs nearly completed. finish briefs output add briefs to summary cleanup some html properly retrieve next and previous commit ids for list navigation follow naddy's stailq macro change we will never have a previous link on the summary page goto correct label, so we get a previous link on the last page of briefs don't wrap short line simplify got_get_repo_commits code start rendering a diff start rendering a diff this was by accident finish diff output functions cleanup prepare for fd request that was a stupid idea, just flush the priv_fd bo that too. that won't work eith with append in mkstemp that isn't going to work actually zero out the priv_fd missed seek to beginning of file was overwriting first line of diff fsync our fd as well add link to repo path by sitelink and add back verbose fcgi debugging that was removed add modest write heuristics to fcgi_send_response fix dead assignments and XXX comment where a leak is happening that I can't find right now there was no leak. stsp is brilliant and knew it was the cache growing prevent double-free, render prettier err output if we can remove unused variables correctly fix double-free fix gotwebd to build with main's changes after rebase fix double-free don't error on index if pack files missing and fixup some error handling render commits finish up tag briefs and start the tag page finish up tag page unbreak TAGS and SUMMARY actions grab the correct tag from the queue unbreak TAGS and SUMMARY actions again update some error handling clean up unneeded code and start tree output render tree render branches remove tags from summary if there aren't any fix tree div structure and start blob render render blob render blame fix tree href in briefs clean up some css add headref to querystrings load correct commit for tree and diff fixup some error output update some copyright dates add full SNI support rm debug line found by Lucas6023, notified via IRC. thanks!! fix tree fix crash when querystring is manipulated to not have a commit id in certain instances. also break a stuck while loop on client error. fix for new got_object_id_by_path arguments rebase and fix prep for multiple fds per socket, instead of just one fix overlooked shift/reduce conflicts backout priv_fds as a list. after discussion with stsp, an array and length are the better direction prepare array of fds to pass into got functions make a new set of pack fds, which will be passed to got_repo_open work with new pack_fds in got_repo_open give output when no tags exist escape html in blame output change files listed in tree view to show blob, file commits, and blame, instead of blob, blob, blame. idea from mp4 on irc. this is way more handy. stop populating the queue from the headref and figure out previous commit id while iterating. this should reduce some overhead. actually purge our sockets instead of not using the function start work with new blob rm volatile use new diff change func names no more temp files increase blame number line width set content-type to text/plain so firefox won't download files rm test infra for now account for -Wwrite-strings fix for sigs and algorithm choice clean up some leaks and other mistakes
- Actions:
- History | Blame | Raw File
1 /*2 * Copyright (c) 2016, 2019, 2020-2022 Tracey Emery <tracey@traceyemery.net>3 * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>4 * Copyright (c) 2013 David Gwynne <dlg@openbsd.org>5 * Copyright (c) 2013 Florian Obser <florian@openbsd.org>6 *7 * Permission to use, copy, modify, and distribute this software for any8 * purpose with or without fee is hereby granted, provided that the above9 * copyright notice and this permission notice appear in all copies.10 *11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.18 */20 #include <netinet/in.h>21 #include <net/if.h>22 #include <sys/queue.h>24 #include <limits.h>25 #include <stdio.h>27 #ifdef DEBUG28 #define dprintf(x...) do { log_debug(x); } while(0)29 #else30 #define dprintf(x...)31 #endif /* DEBUG */33 #ifndef nitems34 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))35 #endif37 /* GOTWEBD DEFAULTS */38 #define GOTWEBD_CONF "/etc/gotwebd.conf"40 #define GOTWEBD_USER "www"42 #define GOTWEBD_MAXCLIENTS 102443 #define GOTWEBD_MAXTEXT 51144 #define GOTWEBD_MAXNAME 6445 #define GOTWEBD_MAXPORT 646 #define GOTWEBD_NUMPROC 347 #define GOTWEBD_MAXIFACE 1649 /* GOTWEB DEFAULTS */50 #define MAX_QUERYSTRING 204851 #define MAX_DOCUMENT_ROOT 25552 #define MAX_SERVER_NAME 25554 #define GOTWEB_GOT_DIR ".got"55 #define GOTWEB_GIT_DIR ".git"57 #define D_HTTPD_CHROOT "/var/www"58 #define D_UNIX_SOCKET "/run/gotweb.sock"59 #define D_FCGI_PORT "9000"60 #define D_GOTPATH "/got/public"61 #define D_SITENAME "Gotweb"62 #define D_SITEOWNER "Got Owner"63 #define D_SITELINK "Repos"64 #define D_GOTLOGO "got.png"65 #define D_GOTURL "https://gameoftrees.org"66 #define D_GOTWEBCSS "gotweb.css"68 #define D_SHOWROWNER 169 #define D_SHOWSOWNER 170 #define D_SHOWAGE 171 #define D_SHOWDESC 172 #define D_SHOWURL 173 #define D_MAXREPO 074 #define D_MAXREPODISP 2575 #define D_MAXSLCOMMDISP 1076 #define D_MAXCOMMITDISP 2578 #define BUF 819280 #define TIMEOUT_DEFAULT 12082 #define FCGI_CONTENT_SIZE 6553583 #define FCGI_PADDING_SIZE 25584 #define FCGI_RECORD_SIZE \85 (sizeof(struct fcgi_record_header) + FCGI_CONTENT_SIZE + FCGI_PADDING_SIZE)87 #define FCGI_ALIGNMENT 888 #define FCGI_ALIGN(n) \89 (((n) + (FCGI_ALIGNMENT - 1)) & ~(FCGI_ALIGNMENT - 1))91 #define FD_RESERVE 592 #define FD_NEEDED 694 #define FCGI_BEGIN_REQUEST 195 #define FCGI_ABORT_REQUEST 296 #define FCGI_END_REQUEST 397 #define FCGI_PARAMS 498 #define FCGI_STDIN 599 #define FCGI_STDOUT 6100 #define FCGI_STDERR 7101 #define FCGI_DATA 8102 #define FCGI_GET_VALUES 9103 #define FCGI_GET_VALUES_RESULT 10104 #define FCGI_UNKNOWN_TYPE 11105 #define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)107 #define FCGI_REQUEST_COMPLETE 0108 #define FCGI_CANT_MPX_CONN 1109 #define FCGI_OVERLOADED 2110 #define FCGI_UNKNOWN_ROLE 3112 /* XXX: move this later after ig */113 #define GOT_PACK_NUM_TEMPFILES 32115 enum imsg_type {116 IMSG_CFG_SRV = IMSG_PROC_MAX,117 IMSG_CFG_SOCK,118 IMSG_CFG_FD,119 IMSG_CFG_DONE,120 IMSG_CTL_START,121 };123 struct env_val {124 SLIST_ENTRY(env_val) entry;125 char *val;126 };127 SLIST_HEAD(env_head, env_val);129 struct fcgi_record_header {130 uint8_t version;131 uint8_t type;132 uint16_t id;133 uint16_t content_len;134 uint8_t padding_len;135 uint8_t reserved;136 }__packed;138 struct fcgi_response {139 TAILQ_ENTRY(fcgi_response) entry;140 uint8_t data[FCGI_RECORD_SIZE];141 size_t data_pos;142 size_t data_len;143 };145 struct repo_dir {146 char *name;147 char *owner;148 char *description;149 char *url;150 char *age;151 char *path;152 };154 struct repo_tag {155 TAILQ_ENTRY(repo_tag) entry;156 char *commit_id;157 char *tag_name;158 char *tag_commit;159 char *commit_msg;160 char *tagger;161 time_t tagger_time;162 };164 struct repo_commit {165 TAILQ_ENTRY(repo_commit) entry;166 char *path;167 char *refs_str;168 char *commit_id; /* id_str1 */169 char *parent_id; /* id_str2 */170 char *tree_id;171 char *author;172 char *committer;173 char *commit_msg;174 time_t committer_time;175 };177 struct got_repository;178 struct transport {179 TAILQ_HEAD(repo_commits_head, repo_commit) repo_commits;180 TAILQ_HEAD(repo_tags_head, repo_tag) repo_tags;181 struct got_repository *repo;182 struct repo_dir *repo_dir;183 struct querystring *qs;184 char *next_id;185 char *prev_id;186 unsigned int repos_total;187 unsigned int next_disp;188 unsigned int prev_disp;189 unsigned int tag_count;190 };192 enum socket_priv_fds {193 DIFF_FD_1,194 DIFF_FD_2,195 DIFF_FD_3,196 DIFF_FD_4,197 DIFF_FD_5,198 BLAME_FD_1,199 BLAME_FD_2,200 BLAME_FD_3,201 BLAME_FD_4,202 BLAME_FD_5,203 BLAME_FD_6,204 BLOB_FD_1,205 BLOB_FD_2,206 PRIV_FDS__MAX,207 };209 struct request {210 struct socket *sock;211 struct server *srv;212 struct transport *t;213 struct event ev;214 struct event tmo;216 uint16_t id;217 int fd;218 int priv_fd[PRIV_FDS__MAX];220 uint8_t buf[FCGI_RECORD_SIZE];221 size_t buf_pos;222 size_t buf_len;224 char querystring[MAX_QUERYSTRING];225 char http_host[GOTWEBD_MAXTEXT];226 char document_root[MAX_DOCUMENT_ROOT];227 char server_name[MAX_SERVER_NAME];229 struct env_head env;230 int env_count;232 uint8_t request_started;233 };235 struct fcgi_begin_request_body {236 uint16_t role;237 uint8_t flags;238 uint8_t reserved[5];239 }__packed;241 struct fcgi_end_request_body {242 uint32_t app_status;243 uint8_t protocol_status;244 uint8_t reserved[3];245 }__packed;247 struct address {248 TAILQ_ENTRY(address) entry;249 struct sockaddr_storage ss;250 int ipproto;251 int prefixlen;252 in_port_t port;253 char ifname[IFNAMSIZ];254 };255 TAILQ_HEAD(addresslist, address);257 struct server {258 TAILQ_ENTRY(server) entry;259 struct addresslist *al;261 char name[GOTWEBD_MAXTEXT];263 char repos_path[PATH_MAX];264 char site_name[GOTWEBD_MAXNAME];265 char site_owner[GOTWEBD_MAXNAME];266 char site_link[GOTWEBD_MAXTEXT];267 char logo[GOTWEBD_MAXTEXT];268 char logo_url[GOTWEBD_MAXTEXT];269 char custom_css[PATH_MAX];271 size_t max_repos;272 size_t max_repos_display;273 size_t max_commits_display;275 int show_site_owner;276 int show_repo_owner;277 int show_repo_age;278 int show_repo_description;279 int show_repo_cloneurl;281 int unix_socket;282 char unix_socket_name[PATH_MAX];284 int fcgi_socket;285 char fcgi_socket_bind[GOTWEBD_MAXTEXT];286 in_port_t fcgi_socket_port;287 };288 TAILQ_HEAD(serverlist, server);290 enum client_action {291 CLIENT_CONNECT,292 CLIENT_DISCONNECT,293 };295 enum sock_type {296 UNIX,297 FCGI,298 };300 struct socket_conf {301 struct addresslist *al;303 char name[GOTWEBD_MAXTEXT];304 char srv_name[GOTWEBD_MAXTEXT];306 int id;307 int child_id;308 int parent_id;310 int ipv4;311 int ipv6;313 int type;314 char unix_socket_name[PATH_MAX];315 in_port_t fcgi_socket_port;316 };318 struct socket {319 TAILQ_ENTRY(socket) entry;320 struct socket_conf conf;322 int fd;323 int pack_fds[GOT_PACK_NUM_TEMPFILES];324 int priv_fd[PRIV_FDS__MAX];326 struct event evt;327 struct event ev;328 struct event pause;330 int client_status;331 };332 TAILQ_HEAD(socketlist, socket);334 struct gotwebd {335 struct serverlist *servers;336 struct socketlist *sockets;338 struct privsep *gotwebd_ps;339 const char *gotwebd_conffile;341 int gotwebd_debug;342 int gotwebd_verbose;343 int gotwebd_noaction;345 uint16_t prefork_gotwebd;346 int gotwebd_reload;348 int server_cnt;350 char httpd_chroot[PATH_MAX];352 int unix_socket;353 char unix_socket_name[PATH_MAX];355 int fcgi_socket;356 char fcgi_socket_bind[GOTWEBD_MAXTEXT];357 in_port_t fcgi_socket_port;358 };360 struct querystring {361 uint8_t action;362 char *commit;363 char *previd;364 char *prevset;365 char *file;366 char *folder;367 char *headref;368 int index_page;369 char *index_page_str;370 char *path;371 int page;372 char *page_str;373 };375 struct querystring_keys {376 const char *name;377 int element;378 };380 struct action_keys {381 const char *name;382 int action;383 };385 enum querystring_elements {386 ACTION,387 COMMIT,388 RFILE,389 FOLDER,390 HEADREF,391 INDEX_PAGE,392 PATH,393 PAGE,394 PREVID,395 QSELEM__MAX,396 };398 enum query_actions {399 BLAME,400 BLOB,401 BRIEFS,402 COMMITS,403 DIFF,404 ERR,405 INDEX,406 SUMMARY,407 TAG,408 TAGS,409 TREE,410 ACTIONS__MAX,411 };413 extern struct gotwebd *gotwebd_env;415 /* sockets.c */416 void sockets(struct privsep *, struct privsep_proc *);417 void sockets_shutdown(void);418 void sockets_parse_sockets(struct gotwebd *);419 void sockets_socket_accept(int, short, void *);420 int sockets_privinit(struct gotwebd *, struct socket *);422 /* gotweb.c */423 const struct got_error *gotweb_render_content_type(struct request *,424 const uint8_t *);425 const struct got_error426 *gotweb_render_content_type_file(struct request *, const uint8_t *, char *);427 const struct got_error *gotweb_get_time_str(char **, time_t, int);428 const struct got_error *gotweb_init_transport(struct transport **);429 const struct got_error *gotweb_escape_html(char **, const char *);430 void gotweb_free_repo_commit(struct repo_commit *);431 void gotweb_free_repo_tag(struct repo_tag *);432 void gotweb_process_request(struct request *);433 void gotweb_free_transport(struct transport *);435 /* parse.y */436 int parse_config(const char *, struct gotwebd *);437 int cmdline_symset(char *);439 /* fcgi.c */440 void fcgi_request(int, short, void *);441 void fcgi_timeout(int, short, void *);442 void fcgi_cleanup_request(struct request *);443 void fcgi_create_end_record(struct request *);444 void dump_fcgi_record(const char *, struct fcgi_record_header *);445 int fcgi_gen_response(struct request *, const char *);446 int fcgi_gen_binary_response(struct request *, const uint8_t *, int);448 /* got_operations.c */449 const struct got_error *got_get_repo_owner(char **, struct request *, char *);450 const struct got_error *got_get_repo_age(char **, struct request *, char *,451 const char *, int);452 const struct got_error *got_get_repo_commits(struct request *, int);453 const struct got_error *got_get_repo_tags(struct request *, int);454 const struct got_error *got_get_repo_heads(struct request *);455 const struct got_error *got_output_repo_diff(struct request *);456 const struct got_error *got_output_repo_tree(struct request *);457 const struct got_error *got_output_file_blob(struct request *);458 const struct got_error *got_output_file_blame(struct request *);460 /* config.c */461 int config_setserver(struct gotwebd *, struct server *);462 int config_getserver(struct gotwebd *, struct imsg *);463 int config_setsock(struct gotwebd *, struct socket *);464 int config_getsock(struct gotwebd *, struct imsg *);465 int config_setfd(struct gotwebd *, struct socket *);466 int config_getfd(struct gotwebd *, struct imsg *);467 int config_getcfg(struct gotwebd *, struct imsg *);468 int config_init(struct gotwebd *);