github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/openstack/obs/http.go (about) 1 // Copyright 2019 Huawei Technologies Co.,Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use 3 // this file except in compliance with the License. You may obtain a copy of the 4 // License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software distributed 9 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 10 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 // specific language governing permissions and limitations under the License. 12 13 package obs 14 15 import ( 16 "bytes" 17 "errors" 18 "fmt" 19 "io" 20 "math/rand" 21 "net" 22 "net/http" 23 "net/url" 24 "os" 25 "strings" 26 "time" 27 ) 28 29 func prepareHeaders(headers map[string][]string, meta bool, isObs bool) map[string][]string { 30 _headers := make(map[string][]string, len(headers)) 31 if headers != nil { 32 for key, value := range headers { 33 key = strings.TrimSpace(key) 34 if key == "" { 35 continue 36 } 37 _key := strings.ToLower(key) 38 if _, ok := allowedRequestHTTPHeaderMetadataNames[_key]; !ok && !strings.HasPrefix(key, HEADER_PREFIX) && !strings.HasPrefix(key, HEADER_PREFIX_OBS) { 39 if !meta { 40 continue 41 } 42 if !isObs { 43 _key = HEADER_PREFIX_META + _key 44 } else { 45 _key = HEADER_PREFIX_META_OBS + _key 46 } 47 } else { 48 _key = key 49 } 50 _headers[_key] = value 51 } 52 } 53 return _headers 54 } 55 56 func (obsClient ObsClient) doActionWithoutBucket(action, method string, input ISerializable, output IBaseModel, extensions []extensionOptions) error { 57 return obsClient.doAction(action, method, "", "", input, output, true, true, extensions) 58 } 59 60 func (obsClient ObsClient) doActionWithBucketV2(action, method, bucketName string, input ISerializable, output IBaseModel, extensions []extensionOptions) error { 61 if strings.TrimSpace(bucketName) == "" && !obsClient.conf.cname { 62 return errors.New("Bucket is empty") 63 } 64 return obsClient.doAction(action, method, bucketName, "", input, output, false, true, extensions) 65 } 66 67 func (obsClient ObsClient) doActionWithBucket(action, method, bucketName string, input ISerializable, output IBaseModel, extensions []extensionOptions) error { 68 if strings.TrimSpace(bucketName) == "" && !obsClient.conf.cname { 69 return errors.New("Bucket is empty") 70 } 71 return obsClient.doAction(action, method, bucketName, "", input, output, true, true, extensions) 72 } 73 74 func (obsClient ObsClient) doActionWithBucketAndKey(action, method, bucketName, objectKey string, input ISerializable, output IBaseModel, extensions []extensionOptions) error { 75 return obsClient._doActionWithBucketAndKey(action, method, bucketName, objectKey, input, output, true, extensions) 76 } 77 78 func (obsClient ObsClient) doActionWithBucketAndKeyV2(action, method, bucketName, objectKey string, input ISerializable, output IBaseModel, extensions []extensionOptions) error { 79 if strings.TrimSpace(bucketName) == "" && !obsClient.conf.cname { 80 return errors.New("Bucket is empty") 81 } 82 if strings.TrimSpace(objectKey) == "" { 83 return errors.New("Key is empty") 84 } 85 return obsClient.doAction(action, method, bucketName, objectKey, input, output, false, true, extensions) 86 } 87 88 func (obsClient ObsClient) doActionWithBucketAndKeyUnRepeatable(action, method, bucketName, objectKey string, input ISerializable, output IBaseModel, extensions []extensionOptions) error { 89 return obsClient._doActionWithBucketAndKey(action, method, bucketName, objectKey, input, output, false, extensions) 90 } 91 92 func (obsClient ObsClient) _doActionWithBucketAndKey(action, method, bucketName, objectKey string, input ISerializable, output IBaseModel, repeatable bool, extensions []extensionOptions) error { 93 if strings.TrimSpace(bucketName) == "" && !obsClient.conf.cname { 94 return errors.New("Bucket is empty") 95 } 96 if strings.TrimSpace(objectKey) == "" { 97 return errors.New("Key is empty") 98 } 99 return obsClient.doAction(action, method, bucketName, objectKey, input, output, true, repeatable, extensions) 100 } 101 102 func (obsClient ObsClient) doAction(action, method, bucketName, objectKey string, input ISerializable, output IBaseModel, xmlResult bool, repeatable bool, extensions []extensionOptions) error { 103 104 var resp *http.Response 105 var respError error 106 doLog(LEVEL_INFO, "Enter method %s...", action) 107 start := GetCurrentTimestamp() 108 109 params, headers, data, err := input.trans(obsClient.conf.signature == SignatureObs) 110 if err != nil { 111 return err 112 } 113 114 if params == nil { 115 params = make(map[string]string) 116 } 117 118 if headers == nil { 119 headers = make(map[string][]string) 120 } 121 122 for _, extension := range extensions { 123 if extensionHeader, ok := extension.(extensionHeaders); ok { 124 _err := extensionHeader(headers, obsClient.conf.signature == SignatureObs) 125 if _err != nil { 126 doLog(LEVEL_INFO, fmt.Sprintf("set header with error: %v", _err)) 127 } 128 } else { 129 doLog(LEVEL_INFO, "Unsupported extensionOptions") 130 } 131 } 132 133 switch method { 134 case HTTP_GET: 135 resp, respError = obsClient.doHTTPGet(bucketName, objectKey, params, headers, data, repeatable) 136 case HTTP_POST: 137 resp, respError = obsClient.doHTTPPost(bucketName, objectKey, params, headers, data, repeatable) 138 case HTTP_PUT: 139 resp, respError = obsClient.doHTTPPut(bucketName, objectKey, params, headers, data, repeatable) 140 case HTTP_DELETE: 141 resp, respError = obsClient.doHTTPDelete(bucketName, objectKey, params, headers, data, repeatable) 142 case HTTP_HEAD: 143 resp, respError = obsClient.doHTTPHead(bucketName, objectKey, params, headers, data, repeatable) 144 case HTTP_OPTIONS: 145 resp, respError = obsClient.doHTTPOptions(bucketName, objectKey, params, headers, data, repeatable) 146 default: 147 respError = errors.New("Unexpect http method error") 148 } 149 if respError == nil && output != nil { 150 respError = ParseResponseToBaseModel(resp, output, xmlResult, obsClient.conf.signature == SignatureObs) 151 if respError != nil { 152 doLog(LEVEL_WARN, "Parse response to BaseModel with error: %v", respError) 153 } 154 } else { 155 doLog(LEVEL_WARN, "Do http request with error: %v", respError) 156 } 157 158 if isDebugLogEnabled() { 159 doLog(LEVEL_DEBUG, "End method %s, obsclient cost %d ms", action, (GetCurrentTimestamp() - start)) 160 } 161 162 return respError 163 } 164 165 func (obsClient ObsClient) doHTTPGet(bucketName, objectKey string, params map[string]string, 166 headers map[string][]string, data interface{}, repeatable bool) (*http.Response, error) { 167 return obsClient.doHTTP(HTTP_GET, bucketName, objectKey, params, prepareHeaders(headers, false, obsClient.conf.signature == SignatureObs), data, repeatable) 168 } 169 170 func (obsClient ObsClient) doHTTPHead(bucketName, objectKey string, params map[string]string, 171 headers map[string][]string, data interface{}, repeatable bool) (*http.Response, error) { 172 return obsClient.doHTTP(HTTP_HEAD, bucketName, objectKey, params, prepareHeaders(headers, false, obsClient.conf.signature == SignatureObs), data, repeatable) 173 } 174 175 func (obsClient ObsClient) doHTTPOptions(bucketName, objectKey string, params map[string]string, 176 headers map[string][]string, data interface{}, repeatable bool) (*http.Response, error) { 177 return obsClient.doHTTP(HTTP_OPTIONS, bucketName, objectKey, params, prepareHeaders(headers, false, obsClient.conf.signature == SignatureObs), data, repeatable) 178 } 179 180 func (obsClient ObsClient) doHTTPDelete(bucketName, objectKey string, params map[string]string, 181 headers map[string][]string, data interface{}, repeatable bool) (*http.Response, error) { 182 return obsClient.doHTTP(HTTP_DELETE, bucketName, objectKey, params, prepareHeaders(headers, false, obsClient.conf.signature == SignatureObs), data, repeatable) 183 } 184 185 func (obsClient ObsClient) doHTTPPut(bucketName, objectKey string, params map[string]string, 186 headers map[string][]string, data interface{}, repeatable bool) (*http.Response, error) { 187 return obsClient.doHTTP(HTTP_PUT, bucketName, objectKey, params, prepareHeaders(headers, true, obsClient.conf.signature == SignatureObs), data, repeatable) 188 } 189 190 func (obsClient ObsClient) doHTTPPost(bucketName, objectKey string, params map[string]string, 191 headers map[string][]string, data interface{}, repeatable bool) (*http.Response, error) { 192 return obsClient.doHTTP(HTTP_POST, bucketName, objectKey, params, prepareHeaders(headers, true, obsClient.conf.signature == SignatureObs), data, repeatable) 193 } 194 195 func prepareAgentHeader(clientUserAgent string) string { 196 userAgent := USER_AGENT 197 if clientUserAgent != "" { 198 userAgent = clientUserAgent 199 } 200 return userAgent 201 } 202 203 func (obsClient ObsClient) getSignedURLResponse(action string, output IBaseModel, xmlResult bool, resp *http.Response, err error, start int64) (respError error) { 204 var msg interface{} 205 if err != nil { 206 respError = err 207 resp = nil 208 } else { 209 doLog(LEVEL_DEBUG, "Response headers: %v", resp.Header) 210 if resp.StatusCode >= 300 { 211 respError = ParseResponseToObsError(resp, obsClient.conf.signature == SignatureObs) 212 msg = resp.Status 213 resp = nil 214 } else { 215 if output != nil { 216 respError = ParseResponseToBaseModel(resp, output, xmlResult, obsClient.conf.signature == SignatureObs) 217 } 218 if respError != nil { 219 doLog(LEVEL_WARN, "Parse response to BaseModel with error: %v", respError) 220 } 221 } 222 } 223 224 if msg != nil { 225 doLog(LEVEL_ERROR, "Failed to send request with reason:%v", msg) 226 } 227 228 if isDebugLogEnabled() { 229 doLog(LEVEL_DEBUG, "End method %s, obsclient cost %d ms", action, (GetCurrentTimestamp() - start)) 230 } 231 return 232 } 233 234 func (obsClient ObsClient) doHTTPWithSignedURL(action, method string, signedURL string, actualSignedRequestHeaders http.Header, data io.Reader, output IBaseModel, xmlResult bool) (respError error) { 235 req, err := http.NewRequest(method, signedURL, data) 236 if err != nil { 237 return err 238 } 239 if obsClient.conf.ctx != nil { 240 req = req.WithContext(obsClient.conf.ctx) 241 } 242 var resp *http.Response 243 244 var isSecurityToken bool 245 var securityToken string 246 var query []string 247 parmas := strings.Split(signedURL, "?") 248 if len(parmas) > 1 { 249 query = strings.Split(parmas[1], "&") 250 for _, value := range query { 251 if strings.HasPrefix(value, HEADER_STS_TOKEN_AMZ+"=") || strings.HasPrefix(value, HEADER_STS_TOKEN_OBS+"=") { 252 if value[len(HEADER_STS_TOKEN_AMZ)+1:] != "" { 253 securityToken = value[len(HEADER_STS_TOKEN_AMZ)+1:] 254 isSecurityToken = true 255 } 256 } 257 } 258 } 259 logSignedURL := signedURL 260 if isSecurityToken { 261 logSignedURL = strings.Replace(logSignedURL, securityToken, "******", -1) 262 } 263 doLog(LEVEL_INFO, "Do %s with signedUrl %s...", action, logSignedURL) 264 265 req.Header = actualSignedRequestHeaders 266 if value, ok := req.Header[HEADER_HOST_CAMEL]; ok { 267 req.Host = value[0] 268 delete(req.Header, HEADER_HOST_CAMEL) 269 } else if value, ok := req.Header[HEADER_HOST]; ok { 270 req.Host = value[0] 271 delete(req.Header, HEADER_HOST) 272 } 273 274 if value, ok := req.Header[HEADER_CONTENT_LENGTH_CAMEL]; ok { 275 req.ContentLength = StringToInt64(value[0], -1) 276 delete(req.Header, HEADER_CONTENT_LENGTH_CAMEL) 277 } else if value, ok := req.Header[HEADER_CONTENT_LENGTH]; ok { 278 req.ContentLength = StringToInt64(value[0], -1) 279 delete(req.Header, HEADER_CONTENT_LENGTH) 280 } 281 282 userAgent := prepareAgentHeader(obsClient.conf.userAgent) 283 req.Header[HEADER_USER_AGENT_CAMEL] = []string{userAgent} 284 start := GetCurrentTimestamp() 285 resp, err = obsClient.httpClient.Do(req) 286 if isInfoLogEnabled() { 287 doLog(LEVEL_INFO, "Do http request cost %d ms", (GetCurrentTimestamp() - start)) 288 } 289 290 respError = obsClient.getSignedURLResponse(action, output, xmlResult, resp, err, start) 291 292 return 293 } 294 295 func prepareData(headers map[string][]string, data interface{}) (io.Reader, error) { 296 var _data io.Reader 297 if data != nil { 298 if dataStr, ok := data.(string); ok { 299 doLog(LEVEL_DEBUG, "Do http request with string: %s", dataStr) 300 headers["Content-Length"] = []string{IntToString(len(dataStr))} 301 _data = strings.NewReader(dataStr) 302 } else if dataByte, ok := data.([]byte); ok { 303 doLog(LEVEL_DEBUG, "Do http request with byte array") 304 headers["Content-Length"] = []string{IntToString(len(dataByte))} 305 _data = bytes.NewReader(dataByte) 306 } else if dataReader, ok := data.(io.Reader); ok { 307 _data = dataReader 308 } else { 309 doLog(LEVEL_WARN, "Data is not a valid io.Reader") 310 return nil, errors.New("Data is not a valid io.Reader") 311 } 312 } 313 return _data, nil 314 } 315 316 func (obsClient ObsClient) getRequest(redirectURL, requestURL string, redirectFlag bool, _data io.Reader, method, 317 bucketName, objectKey string, params map[string]string, headers map[string][]string) (*http.Request, error) { 318 if redirectURL != "" { 319 if !redirectFlag { 320 parsedRedirectURL, err := url.Parse(redirectURL) 321 if err != nil { 322 return nil, err 323 } 324 requestURL, err = obsClient.doAuth(method, bucketName, objectKey, params, headers, parsedRedirectURL.Host) 325 if err != nil { 326 return nil, err 327 } 328 if parsedRequestURL, err := url.Parse(requestURL); err != nil { 329 return nil, err 330 } else if parsedRequestURL.RawQuery != "" && parsedRedirectURL.RawQuery == "" { 331 redirectURL += "?" + parsedRequestURL.RawQuery 332 } 333 } 334 requestURL = redirectURL 335 } else { 336 var err error 337 requestURL, err = obsClient.doAuth(method, bucketName, objectKey, params, headers, "") 338 if err != nil { 339 return nil, err 340 } 341 } 342 343 req, err := http.NewRequest(method, requestURL, _data) 344 if obsClient.conf.ctx != nil { 345 req = req.WithContext(obsClient.conf.ctx) 346 } 347 if err != nil { 348 return nil, err 349 } 350 doLog(LEVEL_DEBUG, "Do request with url [%s] and method [%s]", requestURL, method) 351 return req, nil 352 } 353 354 func logHeaders(headers map[string][]string, signature SignatureType) { 355 if isDebugLogEnabled() { 356 auth := headers[HEADER_AUTH_CAMEL] 357 delete(headers, HEADER_AUTH_CAMEL) 358 359 var isSecurityToken bool 360 var securityToken []string 361 if securityToken, isSecurityToken = headers[HEADER_STS_TOKEN_AMZ]; isSecurityToken { 362 headers[HEADER_STS_TOKEN_AMZ] = []string{"******"} 363 } else if securityToken, isSecurityToken = headers[HEADER_STS_TOKEN_OBS]; isSecurityToken { 364 headers[HEADER_STS_TOKEN_OBS] = []string{"******"} 365 } 366 doLog(LEVEL_DEBUG, "Request headers: %v", headers) 367 headers[HEADER_AUTH_CAMEL] = auth 368 if isSecurityToken { 369 if signature == SignatureObs { 370 headers[HEADER_STS_TOKEN_OBS] = securityToken 371 } else { 372 headers[HEADER_STS_TOKEN_AMZ] = securityToken 373 } 374 } 375 } 376 } 377 378 func prepareReq(headers map[string][]string, req, lastRequest *http.Request, clientUserAgent string) *http.Request { 379 for key, value := range headers { 380 if key == HEADER_HOST_CAMEL { 381 req.Host = value[0] 382 delete(headers, key) 383 } else if key == HEADER_CONTENT_LENGTH_CAMEL { 384 req.ContentLength = StringToInt64(value[0], -1) 385 delete(headers, key) 386 } else { 387 req.Header[key] = value 388 } 389 } 390 391 lastRequest = req 392 393 userAgent := prepareAgentHeader(clientUserAgent) 394 req.Header[HEADER_USER_AGENT_CAMEL] = []string{userAgent} 395 396 if lastRequest != nil { 397 req.Host = lastRequest.Host 398 req.ContentLength = lastRequest.ContentLength 399 } 400 return lastRequest 401 } 402 403 func canNotRetry(repeatable bool, statusCode int) bool { 404 if !repeatable || (statusCode >= 400 && statusCode < 500) || statusCode == 304 { 405 return true 406 } 407 return false 408 } 409 410 func isRedirectErr(location string, redirectCount, maxRedirectCount int) bool { 411 if location != "" && redirectCount < maxRedirectCount { 412 return true 413 } 414 return false 415 } 416 417 func setRedirectFlag(statusCode int, method string) (redirectFlag bool) { 418 if statusCode == 302 && method == HTTP_GET { 419 redirectFlag = true 420 } else { 421 redirectFlag = false 422 } 423 return 424 } 425 426 func prepareRetry(resp *http.Response, headers map[string][]string, _data io.Reader, msg interface{}) (io.Reader, *http.Response, error) { 427 if resp != nil { 428 _err := resp.Body.Close() 429 checkAndLogErr(_err, LEVEL_WARN, "Failed to close resp body") 430 resp = nil 431 } 432 if _, ok := headers[HEADER_AUTH_CAMEL]; ok { 433 delete(headers, HEADER_AUTH_CAMEL) 434 } 435 doLog(LEVEL_WARN, "Failed to send request with reason:%v, will try again", msg) 436 if r, ok := _data.(*strings.Reader); ok { 437 _, err := r.Seek(0, 0) 438 if err != nil { 439 return nil, nil, err 440 } 441 } else if r, ok := _data.(*bytes.Reader); ok { 442 _, err := r.Seek(0, 0) 443 if err != nil { 444 return nil, nil, err 445 } 446 } else if r, ok := _data.(*fileReaderWrapper); ok { 447 fd, err := os.Open(r.filePath) 448 if err != nil { 449 return nil, nil, err 450 } 451 fileReaderWrapper := &fileReaderWrapper{filePath: r.filePath} 452 fileReaderWrapper.mark = r.mark 453 fileReaderWrapper.reader = fd 454 fileReaderWrapper.totalCount = r.totalCount 455 _data = fileReaderWrapper 456 _, err = fd.Seek(r.mark, 0) 457 if err != nil { 458 errMsg := fd.Close() 459 checkAndLogErr(errMsg, LEVEL_WARN, "Failed to close with reason: %v", errMsg) 460 return nil, nil, err 461 } 462 } else if r, ok := _data.(*readerWrapper); ok { 463 _, err := r.seek(0, 0) 464 if err != nil { 465 return nil, nil, err 466 } 467 } 468 return _data, resp, nil 469 } 470 471 func (obsClient ObsClient) doHTTP(method, bucketName, objectKey string, params map[string]string, 472 headers map[string][]string, data interface{}, repeatable bool) (resp *http.Response, respError error) { 473 474 bucketName = strings.TrimSpace(bucketName) 475 476 method = strings.ToUpper(method) 477 478 var redirectURL string 479 var requestURL string 480 maxRetryCount := obsClient.conf.maxRetryCount 481 maxRedirectCount := obsClient.conf.maxRedirectCount 482 483 _data, _err := prepareData(headers, data) 484 if _err != nil { 485 return nil, _err 486 } 487 488 var lastRequest *http.Request 489 redirectFlag := false 490 for i, redirectCount := 0, 0; i <= maxRetryCount; i++ { 491 req, err := obsClient.getRequest(redirectURL, requestURL, redirectFlag, _data, 492 method, bucketName, objectKey, params, headers) 493 if err != nil { 494 return nil, err 495 } 496 497 logHeaders(headers, obsClient.conf.signature) 498 499 lastRequest = prepareReq(headers, req, lastRequest, obsClient.conf.userAgent) 500 501 start := GetCurrentTimestamp() 502 resp, err = obsClient.httpClient.Do(req) 503 doLog(LEVEL_INFO, "Do http request cost %d ms", (GetCurrentTimestamp() - start)) 504 505 var msg interface{} 506 if err != nil { 507 msg = err 508 respError = err 509 resp = nil 510 if !repeatable { 511 break 512 } 513 } else { 514 doLog(LEVEL_DEBUG, "Response headers: %v", resp.Header) 515 if resp.StatusCode < 300 { 516 respError = nil 517 break 518 } else if canNotRetry(repeatable, resp.StatusCode) { 519 respError = ParseResponseToObsError(resp, obsClient.conf.signature == SignatureObs) 520 resp = nil 521 break 522 } else if resp.StatusCode >= 300 && resp.StatusCode < 400 { 523 location := resp.Header.Get(HEADER_LOCATION_CAMEL) 524 if isRedirectErr(location, redirectCount, maxRedirectCount) { 525 redirectURL = location 526 doLog(LEVEL_WARN, "Redirect request to %s", redirectURL) 527 msg = resp.Status 528 maxRetryCount++ 529 redirectCount++ 530 redirectFlag = setRedirectFlag(resp.StatusCode, method) 531 } else { 532 respError = ParseResponseToObsError(resp, obsClient.conf.signature == SignatureObs) 533 resp = nil 534 break 535 } 536 } else { 537 msg = resp.Status 538 } 539 } 540 if i != maxRetryCount { 541 _data, resp, err = prepareRetry(resp, headers, _data, msg) 542 if err != nil { 543 return nil, err 544 } 545 if r, ok := _data.(*fileReaderWrapper); ok { 546 if _fd, _ok := r.reader.(*os.File); _ok { 547 defer func() { 548 errMsg := _fd.Close() 549 checkAndLogErr(errMsg, LEVEL_WARN, "Failed to close with reason: %v", errMsg) 550 }() 551 } 552 } 553 time.Sleep(time.Duration(float64(i+2) * rand.Float64() * float64(time.Second))) 554 } else { 555 doLog(LEVEL_ERROR, "Failed to send request with reason:%v", msg) 556 if resp != nil { 557 respError = ParseResponseToObsError(resp, obsClient.conf.signature == SignatureObs) 558 resp = nil 559 } 560 } 561 } 562 return 563 } 564 565 type connDelegate struct { 566 conn net.Conn 567 socketTimeout time.Duration 568 finalTimeout time.Duration 569 } 570 571 func getConnDelegate(conn net.Conn, socketTimeout int, finalTimeout int) *connDelegate { 572 return &connDelegate{ 573 conn: conn, 574 socketTimeout: time.Second * time.Duration(socketTimeout), 575 finalTimeout: time.Second * time.Duration(finalTimeout), 576 } 577 } 578 579 func (delegate *connDelegate) Read(b []byte) (n int, err error) { 580 setReadDeadlineErr := delegate.SetReadDeadline(time.Now().Add(delegate.socketTimeout)) 581 flag := isDebugLogEnabled() 582 583 if setReadDeadlineErr != nil && flag { 584 doLog(LEVEL_DEBUG, "Failed to set read deadline with reason: %v, but it's ok", setReadDeadlineErr) 585 } 586 587 n, err = delegate.conn.Read(b) 588 setReadDeadlineErr = delegate.SetReadDeadline(time.Now().Add(delegate.finalTimeout)) 589 if setReadDeadlineErr != nil && flag { 590 doLog(LEVEL_DEBUG, "Failed to set read deadline with reason: %v, but it's ok", setReadDeadlineErr) 591 } 592 return n, err 593 } 594 595 func (delegate *connDelegate) Write(b []byte) (n int, err error) { 596 setWriteDeadlineErr := delegate.SetWriteDeadline(time.Now().Add(delegate.socketTimeout)) 597 flag := isDebugLogEnabled() 598 if setWriteDeadlineErr != nil && flag { 599 doLog(LEVEL_DEBUG, "Failed to set write deadline with reason: %v, but it's ok", setWriteDeadlineErr) 600 } 601 602 n, err = delegate.conn.Write(b) 603 finalTimeout := time.Now().Add(delegate.finalTimeout) 604 setWriteDeadlineErr = delegate.SetWriteDeadline(finalTimeout) 605 if setWriteDeadlineErr != nil && flag { 606 doLog(LEVEL_DEBUG, "Failed to set write deadline with reason: %v, but it's ok", setWriteDeadlineErr) 607 } 608 setReadDeadlineErr := delegate.SetReadDeadline(finalTimeout) 609 if setReadDeadlineErr != nil && flag { 610 doLog(LEVEL_DEBUG, "Failed to set read deadline with reason: %v, but it's ok", setReadDeadlineErr) 611 } 612 return n, err 613 } 614 615 func (delegate *connDelegate) Close() error { 616 return delegate.conn.Close() 617 } 618 619 func (delegate *connDelegate) LocalAddr() net.Addr { 620 return delegate.conn.LocalAddr() 621 } 622 623 func (delegate *connDelegate) RemoteAddr() net.Addr { 624 return delegate.conn.RemoteAddr() 625 } 626 627 func (delegate *connDelegate) SetDeadline(t time.Time) error { 628 return delegate.conn.SetDeadline(t) 629 } 630 631 func (delegate *connDelegate) SetReadDeadline(t time.Time) error { 632 return delegate.conn.SetReadDeadline(t) 633 } 634 635 func (delegate *connDelegate) SetWriteDeadline(t time.Time) error { 636 return delegate.conn.SetWriteDeadline(t) 637 }