@@ -102,7 +102,8 @@ var RootCmd = &cobra.Command{
102102 // Use SOCKS5 proxy dialer if specified
103103 dialer , err := proxy .SOCKS5 ("tcp" , proxyAddr [i ], nil , proxy .Direct )
104104 if err != nil {
105- log .Fatalf ("Error creating SOCKS5 dialer: %v" , err )
105+ dmsgcurlLog .WithError (fmt .Errorf ("Error creating SOCKS5 dialer: %v" , err )).Error (errorDesc ["COULDNT_RESOLVE_PROXY" ])
106+ os .Exit (errorCode ["COULDNT_RESOLVE_PROXY" ])
106107 }
107108 transport := & http.Transport {
108109 Dial : dialer .Dial ,
@@ -119,100 +120,124 @@ var RootCmd = &cobra.Command{
119120 pk , sk = cipher .GenerateKeyPair ()
120121 }
121122 if len (args ) == 0 {
122- return errors .New ("no URL(s) provided" )
123+ dmsgcurlLog .WithError (fmt .Errorf ("no URL(s) provided" )).Error (errorDesc ["FAILED_INIT" ])
124+ os .Exit (errorCode ["FAILED_INIT" ])
123125 }
124126 if len (args ) > 1 {
125- return errors .New ("multiple URLs is not yet supported" )
127+ dmsgcurlLog .WithError (fmt .Errorf ("multiple URLs is not yet supported" )).Error (errorDesc ["FAILED_INIT" ])
128+ os .Exit (errorCode ["FAILED_INIT" ])
126129 }
127130 parsedURL , err := url .Parse (args [0 ])
128131 if err != nil {
129- dmsgcurlLog .WithError (err ).Fatal ("failed to parse provided URL" )
132+ dmsgcurlLog .WithError (fmt .Errorf ("failed to parse provided URL" )).Error (errorDesc ["URL_MALFORMAT" ])
133+ os .Exit (errorCode ["URL_MALFORMAT" ])
130134 }
131135 for i := range dmsgDiscs {
132136 if dmsgcurlData != "" {
133- err = handlePostRequest (ctxs [i ], dmsgcurlLog , pk , sk , httpClients [i ], dmsgDiscs [i ], dmsgSessions , parsedURL , dmsgcurlData )
134- if err == nil {
135- return nil
137+ err := handlePostRequest (ctxs [i ], dmsgcurlLog , pk , sk , httpClients [i ], dmsgDiscs [i ], dmsgSessions , parsedURL , dmsgcurlData )
138+ if err .Code != 0 {
139+ dmsgcurlLog .Error (err .Error )
140+ os .Exit (err .Code )
136141 }
137- dmsgcurlLog .WithError (err ).Debug ("An error occurred" )
138142 }
139- err = handleDownload (ctxs [i ], dmsgcurlLog , pk , sk , httpClients [i ], dmsgDiscs [i ], dmsgSessions , parsedURL )
140- if err == nil {
141- return nil
143+ err := handleDownload (ctxs [i ], dmsgcurlLog , pk , sk , httpClients [i ], dmsgDiscs [i ], dmsgSessions , parsedURL )
144+ if err .Code != 0 {
145+ dmsgcurlLog .Error (err .Error )
146+ os .Exit (err .Code )
142147 }
143- dmsgcurlLog .WithError (err ).Debug ("An error occurred" )
144148 }
145- return err
149+ return nil
146150 },
147151}
148152
149- func handlePostRequest (ctx context.Context , dmsgLogger * logging.Logger , pk cipher.PubKey , sk cipher.SecKey , httpClient * http.Client , dmsgDisc string , dmsgSessions int , parsedURL * url.URL , dmsgcurlData string ) error {
153+ func handlePostRequest (ctx context.Context , dmsgLogger * logging.Logger , pk cipher.PubKey , sk cipher.SecKey , httpClient * http.Client , dmsgDisc string , dmsgSessions int , parsedURL * url.URL , dmsgcurlData string ) curlError {
150154 dmsgC , closeDmsg , err := cli .StartDmsg (ctx , dmsgLogger , pk , sk , httpClient , dmsgDisc , dmsgSessions )
151155 if err != nil {
152- dmsgcurlLog .WithError (err ).Warnf ("Failed to start dmsg" )
153- return err
156+ return curlError {
157+ Error : fmt .Errorf ("%s" , errorDesc ["DMSG_INIT" ]),
158+ Code : errorCode ["DMSG_INIT" ],
159+ }
154160 }
155161 defer closeDmsg ()
156162
157163 httpC := http.Client {Transport : dmsghttp .MakeHTTPTransport (ctx , dmsgC )}
158164 req , err := http .NewRequest (http .MethodPost , parsedURL .String (), strings .NewReader (dmsgcurlData ))
159165 if err != nil {
160- dmsgcurlLog .WithError (err ).Fatal ("Failed to formulate HTTP request." )
166+ return curlError {
167+ Error : fmt .Errorf ("%s" , errorDesc ["URL_MALFORMAT" ]),
168+ Code : errorCode ["URL_MALFORMAT" ],
169+ }
161170 }
162171 req .Header .Set ("Content-Type" , "text/plain" )
163172
164173 resp , err := httpC .Do (req )
165174 if err != nil {
166- dmsgcurlLog .WithError (err ).Debug ("Failed to execute HTTP request" )
175+ return curlError {
176+ Error : fmt .Errorf ("%s" , errorDesc ["COULDNT_RESOLVE_HOST" ]),
177+ Code : errorCode ["COULDNT_RESOLVE_HOST" ],
178+ }
167179 }
168180 defer closeResponseBody (resp )
169181
170182 respBody , err := io .ReadAll (resp .Body )
171183 if err != nil {
172- dmsgcurlLog .WithError (err ).Debug ("Failed to read response body." )
173- return err
184+ return curlError {
185+ Error : fmt .Errorf ("%s" , errorDesc ["READ_ERROR" ]),
186+ Code : errorCode ["READ_ERROR" ],
187+ }
174188 }
175189 fmt .Println (string (respBody ))
176- return nil
190+ return curlError {}
177191
178192}
179193
180- func handleDownload (ctx context.Context , dmsgLogger * logging.Logger , pk cipher.PubKey , sk cipher.SecKey , httpClient * http.Client , dmsgDisc string , dmsgSessions int , parsedURL * url.URL ) error {
194+ func handleDownload (ctx context.Context , dmsgLogger * logging.Logger , pk cipher.PubKey , sk cipher.SecKey , httpClient * http.Client , dmsgDisc string , dmsgSessions int , parsedURL * url.URL ) curlError {
181195 file , err := prepareOutputFile ()
182196 if err != nil {
183- return fmt .Errorf ("failed to prepare output file: %w" , err )
197+ return curlError {
198+ Error : fmt .Errorf ("%s" , errorDesc ["WRITE_INIT" ]),
199+ Code : errorCode ["WRITE_INIT" ],
200+ }
184201 }
185202 defer closeAndCleanFile (file , err )
186203
187204 dmsgC , closeDmsg , err := cli .StartDmsg (ctx , dmsgLogger , pk , sk , httpClient , dmsgDisc , dmsgSessions )
188205 if err != nil {
189- dmsgcurlLog .WithError (err ).Warnf ("Failed to start dmsg" )
190- return err
206+ return curlError {
207+ Error : fmt .Errorf ("%s" , errorDesc ["DMSG_INIT" ]),
208+ Code : errorCode ["DMSG_INIT" ],
209+ }
191210 }
192211 defer closeDmsg ()
193212
194213 httpC := http.Client {Transport : dmsghttp .MakeHTTPTransport (ctx , dmsgC )}
195214
215+ var downloadErr curlError
196216 for i := 0 ; i < dmsgcurlTries ; i ++ {
197217 if dmsgcurlOutput != "" {
198218 dmsgcurlLog .Debugf ("Download attempt %d/%d ..." , i , dmsgcurlTries )
199219 if _ , err := file .Seek (0 , 0 ); err != nil {
200- return fmt .Errorf ("failed to reset file: %w" , err )
220+ return curlError {
221+ Error : fmt .Errorf ("%s" , errorDesc ["WRITE_ERROR" ]),
222+ Code : errorCode ["WRITE_ERROR" ],
223+ }
201224 }
202225 }
203- if err : = download (ctx , dmsgcurlLog , & httpC , file , parsedURL .String (), 0 ); err != nil {
226+ if downloadErr = download (ctx , dmsgcurlLog , & httpC , file , parsedURL .String (), 0 ); downloadErr . Code != 0 {
204227 dmsgcurlLog .WithError (err ).Error ()
205228 select {
206229 case <- ctx .Done ():
207- return ctx .Err ()
230+ return curlError {
231+ Error : fmt .Errorf ("%s" , errorDesc ["CONTEXT_CANCELED" ]),
232+ Code : errorCode ["CONTEXT_CANCELED" ],
233+ }
208234 case <- time .After (time .Duration (dmsgcurlWait ) * time .Second ):
209235 continue
210236 }
211237 }
212-
213- return nil
238+ return downloadErr
214239 }
215- return err
240+ return downloadErr
216241}
217242
218243func prepareOutputFile () (* os.File , error ) {
@@ -260,25 +285,37 @@ func parseOutputFile(output string, replace bool) (*os.File, error) {
260285 return nil , os .ErrExist
261286}
262287
263- func download (ctx context.Context , log logrus.FieldLogger , httpC * http.Client , w io.Writer , urlStr string , maxSize int64 ) error {
288+ func download (ctx context.Context , log logrus.FieldLogger , httpC * http.Client , w io.Writer , urlStr string , maxSize int64 ) curlError {
264289 req , err := http .NewRequest (http .MethodGet , urlStr , nil )
265290 if err != nil {
266291 log .WithError (err ).Fatal ("Failed to formulate HTTP request." )
267292 }
268293 resp , err := httpC .Do (req )
269294 if err != nil {
270- return fmt .Errorf ("failed to connect to HTTP server: %w" , err )
295+ log .Errorf ("failed to connect to HTTP server: %w" , err )
296+ return curlError {
297+ Error : fmt .Errorf ("%s" , errorDesc ["RECV_ERROR" ]),
298+ Code : errorCode ["RECV_ERROR" ],
299+ }
271300 }
272301 if maxSize > 0 && resp .ContentLength > maxSize * 1024 {
273- return fmt .Errorf ("requested file size is more than allowed size: %d KB > %d KB" , (resp .ContentLength / 1024 ), maxSize )
302+ log .Errorf ("requested file size is more than allowed size: %d KB > %d KB" , (resp .ContentLength / 1024 ), maxSize )
303+ return curlError {
304+ Error : fmt .Errorf ("%s" , errorDesc ["FILESIZE_EXCEEDED" ]),
305+ Code : errorCode ["FILESIZE_EXCEEDED" ],
306+ }
274307 }
275308 n , err := cancellableCopy (ctx , w , resp .Body , resp .ContentLength )
276309 if err != nil {
277- return fmt .Errorf ("download failed at %d/%dB: %w" , n , resp .ContentLength , err )
310+ log .Errorf ("download failed at %d/%dB: %w" , n , resp .ContentLength , err )
311+ return curlError {
312+ Error : fmt .Errorf ("%s" , errorDesc ["DOWNLOAD_ERROR" ]),
313+ Code : errorCode ["DOWNLOAD_ERROR" ],
314+ }
278315 }
279316 defer closeResponseBody (resp )
280317
281- return nil
318+ return curlError {}
282319}
283320
284321type readerFunc func (p []byte ) (n int , err error )
@@ -324,3 +361,9 @@ func Execute() {
324361 log .Fatal ("Failed to execute command: " , err )
325362 }
326363}
364+
365+ // curlError the struct of dmsgcurl functions output for use exit code as result
366+ type curlError struct {
367+ Error error
368+ Code int
369+ }
0 commit comments