Browse code
feat: get rid of *default-client* for multithreading
Edward authored on 30/11/2020 01:53:06
Showing 3 changed files
Showing 3 changed files
... | ... |
@@ -1,10 +1,5 @@ |
1 | 1 |
(in-package #:com.liotev.nntp) |
2 | 2 |
|
3 |
-(defparameter *default-client* nil |
|
4 |
- "This client will be used in all functions that accept a client as an |
|
5 |
-optional parameter, and this optional parameter is not supplied or |
|
6 |
-nil.") |
|
7 |
- |
|
8 | 3 |
(defparameter *cache-authinfo-p* nil |
9 | 4 |
"If t, the user name and password will be saved in the client |
10 | 5 |
object.") |
... | ... |
@@ -83,7 +78,6 @@ client." |
83 | 78 |
(make-new-client host port stream server-greeting |
84 | 79 |
tls-p))) |
85 | 80 |
(register-client new-client) |
86 |
- (setf *default-client* new-client) |
|
87 | 81 |
(when auth (authenticate-client new-client))) |
88 | 82 |
(progn |
89 | 83 |
(reset-client client host port stream server-greeting |
... | ... |
@@ -121,7 +115,7 @@ client." |
121 | 115 |
|
122 | 116 |
|
123 | 117 |
(defun do-command |
124 |
- (command &optional (client *default-client*) |
|
118 |
+ (command client |
|
125 | 119 |
&key (reconnect t reconnect-supplied-p)) |
126 | 120 |
"Sends the command to the server. In case of a timeout message from |
127 | 121 |
the server, a reconnect will be attempted in the following cases: |
... | ... |
@@ -150,7 +144,7 @@ In case of another error, a reconnect will be attempted if |
150 | 144 |
(when (find-restart 'reconnect) |
151 | 145 |
(invoke-restart 'reconnect)) ) |
152 | 146 |
|
153 |
-(defun send-command (command &optional (client *default-client*)) |
|
147 |
+(defun send-command (command client) |
|
154 | 148 |
"Sends the command to the server." |
155 | 149 |
(setf (client-last-command client) command) |
156 | 150 |
(restart-case |
... | ... |
@@ -177,7 +171,7 @@ In case of another error, a reconnect will be attempted if |
177 | 171 |
t)) |
178 | 172 |
|
179 | 173 |
|
180 |
-(defun group (group-name &optional (client *default-client*)) |
|
174 |
+(defun group (group-name client) |
|
181 | 175 |
"The GROUP nntp command. |
182 | 176 |
Syntax |
183 | 177 |
GROUP group |
... | ... |
@@ -195,7 +189,29 @@ Parameters |
195 | 189 |
(setf (client-group client) group-name) |
196 | 190 |
(do-command (str "group " group-name) client)) |
197 | 191 |
|
198 |
-(defun article (&optional (client *default-client*) |
|
192 |
+(defun listgroup (group-name client) |
|
193 |
+ "The LISTGROUP nntp command. |
|
194 |
+Syntax |
|
195 |
+ LISTGROUP group |
|
196 |
+ |
|
197 |
+Responses |
|
198 |
+ 211 number low high group Group successfully selected |
|
199 |
+ 411 No such newsgroup |
|
200 |
+ |
|
201 |
+Parameters |
|
202 |
+ group Name of newsgroup |
|
203 |
+ number Estimated number of articles in the group |
|
204 |
+ low Reported low water mark |
|
205 |
+ high Reported high water mark |
|
206 |
+" |
|
207 |
+ (setf (client-group client) group-name) |
|
208 |
+ (let ((result (do-command (str "listgroup " group-name) client))) |
|
209 |
+ (values (mapcar (lambda (it) |
|
210 |
+ (parse-integer it :junk-allowed t)) |
|
211 |
+ (get-multi-line-response client)) |
|
212 |
+ result))) |
|
213 |
+ |
|
214 |
+(defun article (client |
|
199 | 215 |
&key article-number article-id) |
200 | 216 |
"Retreives an article. |
201 | 217 |
Syntax |
... | ... |
@@ -229,8 +245,7 @@ Parameters |
229 | 245 |
(when (string= "220" (client-status-code client)) |
230 | 246 |
(get-block-response client))) |
231 | 247 |
|
232 |
-(defun head (&optional (client *default-client*) |
|
233 |
- &key article-number article-id) |
|
248 |
+(defun head (client &key article-number article-id) |
|
234 | 249 |
"Retreives the article headers. |
235 | 250 |
Syntax |
236 | 251 |
HEAD message-id |
... | ... |
@@ -258,8 +273,7 @@ Parameters |
258 | 273 |
(when (string= "221" (client-status-code client)) |
259 | 274 |
(get-block-response client))) |
260 | 275 |
|
261 |
-(defun body (&optional (client *default-client*) |
|
262 |
- &key article-number article-id) |
|
276 |
+(defun body (client &key article-number article-id) |
|
263 | 277 |
"Retreives the article body |
264 | 278 |
Syntax |
265 | 279 |
BODY message-id |
... | ... |
@@ -292,8 +306,7 @@ Parameters |
292 | 306 |
(when (string= "222" (client-status-code client)) |
293 | 307 |
(get-block-response client))) |
294 | 308 |
|
295 |
-(defun stat (&optional(client *default-client*) |
|
296 |
- &key article-number article-id) |
|
309 |
+(defun stat (client &key article-number article-id) |
|
297 | 310 |
"Determines if an article exists, or the message |
298 | 311 |
id of the article. |
299 | 312 |
|
... | ... |
@@ -326,7 +339,7 @@ Parameters |
326 | 339 |
(article-command "stat" client :article-number article-number |
327 | 340 |
:article-id article-id)) |
328 | 341 |
|
329 |
-(defun capabilities (&optional (client *default-client*)) |
|
342 |
+(defun capabilities (client) |
|
330 | 343 |
"Lists the capabilities of the server. |
331 | 344 |
Syntax |
332 | 345 |
CAPABILITIES [keyword] |
... | ... |
@@ -336,18 +349,18 @@ Responses |
336 | 349 |
" |
337 | 350 |
(block-command "CAPABILITIES" (list "101") client)) |
338 | 351 |
|
339 |
-(defun help (&optional (client *default-client*)) |
|
352 |
+(defun help (client) |
|
340 | 353 |
(block-command "help" (list "100") client)) |
341 | 354 |
|
342 | 355 |
(defun block-command (command valid-codes |
343 |
- &optional (client *default-client*)) |
|
356 |
+ client) |
|
344 | 357 |
"Sends a command that expects a block and retreives the block |
345 | 358 |
response." |
346 | 359 |
(do-command command client) |
347 | 360 |
(when (find (client-status-code client) valid-codes :test #'string=) |
348 | 361 |
(get-block-response client))) |
349 | 362 |
|
350 |
-(defun article-command (command &optional (client *default-client*) |
|
363 |
+(defun article-command (command client |
|
351 | 364 |
&key article-number article-id) |
352 | 365 |
"Performs an articla related command. Can be one of 'ARTICLE', 'HEAD', |
353 | 366 |
'BODY', 'STAT'." |
... | ... |
@@ -363,13 +376,12 @@ response." |
363 | 376 |
:article-id article-id) |
364 | 377 |
(do-command full-command client)))) |
365 | 378 |
|
366 |
-(defun set-article (&optional(client *default-client*) |
|
367 |
- &key article-number article-id) |
|
379 |
+(defun set-article (client &key article-number article-id) |
|
368 | 380 |
"Sets the article in the client" |
369 | 381 |
(setf (client-article-number client) article-number |
370 | 382 |
(client-article-id client) article-id)) |
371 | 383 |
|
372 |
-(defun get-status (&optional (client *default-client*)) |
|
384 |
+(defun get-status (client) |
|
373 | 385 |
"Reads the status line of the server response, retrurn status code and |
374 | 386 |
status message." |
375 | 387 |
(let ((line (client-read-line client))) |
... | ... |
@@ -384,7 +396,16 @@ status message." |
384 | 396 |
(values status-code status-message))) |
385 | 397 |
(error "No response from the server")))) |
386 | 398 |
|
387 |
-(defun authinfo (user pass &optional (client *default-client*)) |
|
399 |
+(defun get-multi-line-response (client) |
|
400 |
+ (loop for line = (cl-nntp::client-read-line client) |
|
401 |
+ until (string= line #.(coerce #(#\. #\return) 'string)) |
|
402 |
+ collect |
|
403 |
+ (if (and (> (length line) 2) |
|
404 |
+ (string= ".." line :end2 2)) |
|
405 |
+ (subseq line 1) |
|
406 |
+ line))) |
|
407 |
+ |
|
408 |
+(defun authinfo (user pass client) |
|
388 | 409 |
"Authenticates the client." |
389 | 410 |
(when (null client) (error "Can not authenticate NIL client")) |
390 | 411 |
(when *cache-authinfo-p* |
... | ... |
@@ -411,28 +432,28 @@ status message." |
411 | 432 |
(user (client-user client))) |
412 | 433 |
(if user (str user "@" name) name))) |
413 | 434 |
|
414 |
-(defun authinfo-user (user &optional (client *default-client*)) |
|
435 |
+(defun authinfo-user (user client) |
|
415 | 436 |
"Sends the 'authinfo user' command." |
416 | 437 |
(let ((command (str "AUTHINFO USER " user))) |
417 | 438 |
(client-write-line command client) |
418 | 439 |
(get-status client))) |
419 | 440 |
|
420 |
-(defun authinfo-pass (pass &optional (client *default-client*)) |
|
441 |
+(defun authinfo-pass (pass client) |
|
421 | 442 |
"Sends the 'authinfo pass' command." |
422 | 443 |
(let ((command (str "AUTHINFO PASS " pass))) |
423 | 444 |
(client-write-line command client) |
424 | 445 |
(get-status client))) |
425 | 446 |
|
426 |
-(defun date (&optional (client *default-client*)) |
|
447 |
+(defun date (client) |
|
427 | 448 |
(do-command "date" client)) |
428 | 449 |
|
429 |
-(defun last-article (&optional (client *default-client*)) |
|
450 |
+(defun last-article (client) |
|
430 | 451 |
(do-command "last" client)) |
431 | 452 |
|
432 |
-(defun next-article (&optional (client *default-client*)) |
|
453 |
+(defun next-article (client) |
|
433 | 454 |
(do-command "next" client)) |
434 | 455 |
|
435 |
-(defun get-block-response (&optional (client *default-client*)) |
|
456 |
+(defun get-block-response (client) |
|
436 | 457 |
"Reads a block response." |
437 | 458 |
(let ((stream (client-stream client))) |
438 | 459 |
(with-output-to-string (s) |
... | ... |
@@ -453,7 +474,7 @@ status message." |
453 | 474 |
status-code |
454 | 475 |
nil)) |
455 | 476 |
|
456 |
-(defun disconnect-client (&optional (client *default-client*)) |
|
477 |
+(defun disconnect-client (client) |
|
457 | 478 |
(let ((stream (client-stream client))) |
458 | 479 |
(when (or (null stream) |
459 | 480 |
(not (open-stream-p stream))) |
... | ... |
@@ -466,13 +487,11 @@ status message." |
466 | 487 |
(setf (client-stream client) nil)) |
467 | 488 |
client)) |
468 | 489 |
|
469 |
-(defun destroy-client (&optional (client *default-client*)) |
|
490 |
+(defun destroy-client (client) |
|
470 | 491 |
(disconnect-client client) |
471 |
- (setf *clients* (delete client *clients*)) |
|
472 |
- (when (eq *default-client* client) |
|
473 |
- (setf *default-client* (car *clients*)))) |
|
492 |
+ (setf *clients* (delete client *clients*))) |
|
474 | 493 |
|
475 |
-(defun reconnect-client (&optional (client *default-client*)) |
|
494 |
+(defun reconnect-client (client) |
|
476 | 495 |
(connect (client-host client) (client-port client) client) |
477 | 496 |
(when (client-group client) |
478 | 497 |
(let ((command (str "group " (client-group client)))) |