git.fiddlerwoaroof.com
Browse code

feat: get rid of *default-client* for multithreading

Edward authored on 30/11/2020 01:53:06
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))))
... ...
@@ -19,7 +19,7 @@
19 19
            #:capabilities
20 20
            #:date
21 21
            #:quit
22
-           ;; #:listgroup
22
+           #:listgroup
23 23
            ;; #:mode-reader
24 24
            ;; #:list
25 25
            ;; #:newsgroups
... ...
@@ -43,7 +43,7 @@
43 43
    #+CLISP (ext:getenv name)
44 44
    #+ECL (si:getenv name)
45 45
    #+SBCL (sb-unix::posix-getenv name)
46
-   #+LISPWORKS (lispwrks:environment-variable name)
46
+   #+LISPWORKS (lispworks:environment-variable name)
47 47
    #+CCL (getenv name)
48 48
    default))
49 49