Statistics
| Branch: | Tag: | Revision:

dvbd / outputbuffer.cpp @ bfdb7446

History | View | Annotate | Download (2.62 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18

    
19
#include "config.h"
20
#include "outputbuffer.h"
21
#include "dvbd.h"
22

    
23
#include <unistd.h>
24
#include <iostream>
25
#include <sys/types.h>
26
#include <sys/socket.h>
27
#include <sys/un.h>
28

    
29
OutputBuffer::OutputBuffer(int fd, int initSize, int maxSize)
30
  : CircularBuffer(initSize, maxSize), fd(fd)
31
{
32
}
33

    
34
OutputBuffer::~OutputBuffer()
35
{
36
}
37

    
38
void OutputBuffer::addSelectFDs(Select &s) const
39
{
40
  if (getUsed() > 0)
41
    s.addWriteFD(fd);
42
}
43

    
44
bool OutputBuffer::isReady(const Select &s) const
45
{
46
  return s.readyToWrite(fd);
47
}
48

    
49
bool OutputBuffer::process()
50
{
51
  if (getUsed() == 0)
52
    return true;
53

    
54
  // We are using a circular buffer. 
55
  // Write only the first half (if there is a second
56
  // half, we will get it next round).
57

    
58
  char *buffer1, *buffer2;
59
  int length1, length2;
60

    
61
  getSections(buffer1, length1, buffer2, length2);
62

    
63
  if (length1 == 0) {
64
    buffer1 = buffer2;
65
    length1 = length2;
66
  }
67

    
68
  int bytesWritten = ::write(fd, buffer1, length1);
69

    
70
  if (bytesWritten <= 0)
71
    return false;
72

    
73
  discard(bytesWritten);
74
  return true;
75
}
76

    
77
bool OutputBuffer::flush()
78
{
79
  // Flush the entire output buffer (blocking)
80
  Select s;
81

    
82
  while (getUsed() > 0) {
83
    addSelectFDs(s);
84
    s.wait();
85

    
86
    if (!isReady(s))
87
      return false;
88

    
89
    if (!process())
90
      return false;
91
    
92
    s.clearFDs();
93
  }
94
  return true;
95
}
96

    
97
bool OutputBuffer::writeCredentials()
98
{
99
  struct msghdr msg;
100
  char buffer[CMSG_SPACE(sizeof(struct ucred))];
101

    
102
  msg.msg_name = NULL;
103
  msg.msg_namelen = 0;
104
  msg.msg_iov = 0;
105
  msg.msg_iovlen = 0;
106
  msg.msg_control = buffer;
107
  msg.msg_controllen = sizeof(buffer);
108
  msg.msg_flags = 0;
109

    
110
  struct ucred ucred;
111
  ucred.pid = getpid();
112
  ucred.uid = getuid();
113
  ucred.gid = getgid();
114

    
115
  struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
116
  cmsg->cmsg_level = SOL_SOCKET;
117
  cmsg->cmsg_type = SCM_CREDENTIALS;
118
  cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
119
  memcpy(CMSG_DATA(cmsg), &ucred, sizeof(struct ucred));
120

    
121
  return sendmsg(fd, &msg, 0) >= 0;
122
}
123