Write encrypts, frames, and writes bytes from b to the underlying connection.
(b []byte)
| 311 | |
| 312 | // Write encrypts, frames, and writes bytes from b to the underlying connection. |
| 313 | func (p *conn) Write(b []byte) (n int, err error) { |
| 314 | n = len(b) |
| 315 | // Calculate the output buffer size with framing and encryption overhead. |
| 316 | numOfFrames := int(math.Ceil(float64(len(b)) / float64(p.payloadLengthLimit))) |
| 317 | size := len(b) + numOfFrames*p.overhead |
| 318 | partialBSize := len(b) |
| 319 | if size > altsWriteBufferMaxSize { |
| 320 | size = altsWriteBufferMaxSize |
| 321 | const numOfFramesInMaxWriteBuf = altsWriteBufferMaxSize / altsRecordDefaultLength |
| 322 | partialBSize = numOfFramesInMaxWriteBuf * p.payloadLengthLimit |
| 323 | } |
| 324 | // Get a writeBuf of the required length. |
| 325 | bufHandle := writeBufPool.Get(size) |
| 326 | defer writeBufPool.Put(bufHandle) |
| 327 | writeBuf := *bufHandle |
| 328 | |
| 329 | for partialBStart := 0; partialBStart < len(b); partialBStart += partialBSize { |
| 330 | partialBEnd := min(partialBStart+partialBSize, len(b)) |
| 331 | partialB := b[partialBStart:partialBEnd] |
| 332 | writeBufIndex := 0 |
| 333 | for len(partialB) > 0 { |
| 334 | payloadLen := min(len(partialB), p.payloadLengthLimit) |
| 335 | buf := partialB[:payloadLen] |
| 336 | partialB = partialB[payloadLen:] |
| 337 | |
| 338 | // Write buffer contains: length, type, payload, and tag |
| 339 | // if any. |
| 340 | |
| 341 | // 1. Fill in type field. |
| 342 | msg := writeBuf[writeBufIndex+MsgLenFieldSize:] |
| 343 | binary.LittleEndian.PutUint32(msg, altsRecordMsgType) |
| 344 | |
| 345 | // 2. Encrypt the payload and create a tag if any. |
| 346 | msg, err = p.crypto.Encrypt(msg[:msgTypeFieldSize], buf) |
| 347 | if err != nil { |
| 348 | return n, err |
| 349 | } |
| 350 | |
| 351 | // 3. Fill in the size field. |
| 352 | binary.LittleEndian.PutUint32(writeBuf[writeBufIndex:], uint32(len(msg))) |
| 353 | |
| 354 | // 4. Increase writeBufIndex. |
| 355 | writeBufIndex += len(buf) + p.overhead |
| 356 | } |
| 357 | nn, err := p.Conn.Write(writeBuf[:writeBufIndex]) |
| 358 | if err != nil { |
| 359 | // We need to calculate the actual data size that was |
| 360 | // written. This means we need to remove header, |
| 361 | // encryption overheads, and any partially-written |
| 362 | // frame data. |
| 363 | numOfWrittenFrames := int(math.Floor(float64(nn) / float64(altsRecordDefaultLength))) |
| 364 | return partialBStart + numOfWrittenFrames*p.payloadLengthLimit, err |
| 365 | } |
| 366 | } |
| 367 | return n, nil |
| 368 | } |