(dst io.Writer, src io.Reader, key *[ivLen]byte, config IOConfig)
| 309 | } |
| 310 | |
| 311 | func (iot *io_t) Copy(dst io.Writer, src io.Reader, key *[ivLen]byte, config IOConfig) (written int64, err error) { |
| 312 | if iot.Logger.GetLevel() == logg.LvDebug { |
| 313 | defer func() { |
| 314 | if r := recover(); r != nil { |
| 315 | iot.Logger.E("Copy Panic", r) |
| 316 | } |
| 317 | }() |
| 318 | } |
| 319 | |
| 320 | buf := make([]byte, 32*1024) |
| 321 | ctr := (*Cipher)(unsafe.Pointer(iot)).getCipherStream(key) |
| 322 | encrypted := 0 |
| 323 | |
| 324 | u := atomic.AddUint64(&iot.iid, 1) |
| 325 | |
| 326 | for { |
| 327 | iot.markActive(src, u) |
| 328 | var nr int |
| 329 | var er error |
| 330 | |
| 331 | switch config.WSCtrl { |
| 332 | case wsClientSrcIsUpstream, wsServerSrcIsDownstream: |
| 333 | // we are client, reading from upstream, or |
| 334 | // we are server, reading from downstream |
| 335 | buf, nr, er = iot.wsRead(src) |
| 336 | default: |
| 337 | nr, er = src.Read(buf) |
| 338 | } |
| 339 | if nr > 0 { |
| 340 | xbuf := buf[0:nr] |
| 341 | if config.Role == roleSend { |
| 342 | iot.Tr.Send(int64(nr)) |
| 343 | } else if config.Role == roleRecv { |
| 344 | iot.Tr.Recv(int64(nr)) |
| 345 | } |
| 346 | |
| 347 | if config.Partial && encrypted == sslRecordLen { |
| 348 | // goto direct_transmission |
| 349 | } else if ctr != nil { |
| 350 | |
| 351 | if encrypted+nr > sslRecordLen && config.Partial { |
| 352 | ybuf := xbuf[:sslRecordLen-encrypted] |
| 353 | ctr.XORKeyStream(ybuf, ybuf) |
| 354 | encrypted = sslRecordLen |
| 355 | // we are done, the traffic coming later will be transfered as is |
| 356 | } else { |
| 357 | ctr.XORKeyStream(xbuf, xbuf) |
| 358 | encrypted += nr |
| 359 | } |
| 360 | |
| 361 | } |
| 362 | |
| 363 | if config.Bucket != nil { |
| 364 | config.Bucket.Consume(int64(len(xbuf))) |
| 365 | } |
| 366 | |
| 367 | var nw int |
| 368 | var ew error |
no test coverage detected